当前位置:  开发笔记 > 编程语言 > 正文

使用包含图像的Retrofit 2.0 POST多部分表单数据

如何解决《使用包含图像的Retrofit2.0POST多部分表单数据》经验,为你挑选了6个好方法。

我正在尝试使用Retrofit 2.0对服务器进行HTTP POST

MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/plain");
MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*");

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    imageBitmap.compress(Bitmap.CompressFormat.JPEG,90,byteArrayOutputStream);
profilePictureByte = byteArrayOutputStream.toByteArray();

Call call = ServiceAPI.updateProfile(
        RequestBody.create(MEDIA_TYPE_TEXT, emailString),
        RequestBody.create(MEDIA_TYPE_IMAGE, profilePictureByte));

call.enqueue();

服务器返回错误,指出文件无效.

这很奇怪,因为我试图在iOS上使用相同的格式上传相同的文件(使用其他库),但它上传成功.

我想知道使用Retrofit 2.0上传图像的正确方法是什么?

在上传之前我应该​​先将它保存到磁盘吗?

谢谢!

PS:我已经将改造用于其他不包含图像的Multipart请求,并且已成功完成.问题是当我试图在主体中包含一个字节时.



1> insomniac..:

我正在强调1.9和2.0中的解决方案,因为它对某些人有用

1.9,我认为更好的解决方案是将文件保存到磁盘并将其用作类型文件,如:

RetroFit 1.9

(我不知道你的服务器端实现)有一个类似于此的API接口方法

@POST("/en/Api/Results/UploadFile")
void UploadFile(@Part("file")TypedFile file,@Part("folder")String folder,Callback callback);

并使用它

TypedFile file = new TypedFile("multipart/form-data", new File(path));

对于RetroFit 2使用以下方法

RetroFit 2.0(这是针对RetroFit 2中的一个问题的解决方法,现在已修复,正确的方法请参考jimmy0251的答案)

API接口:

public interface ApiInterface {
    @Multipart
    @POST("/api/Accounts/editaccount")
    Call editUser (@Header("Authorization") String authorization, @Part("file\"; filename=\"pp.png\" ") RequestBody file , @Part("FirstName") RequestBody fname, @Part("Id") RequestBody id);
}

使用它像:

File file = new File(imageUri.getPath());
RequestBody fbody = RequestBody.create(MediaType.parse("image/*"), file);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), firstNameField.getText().toString());
RequestBody id = RequestBody.create(MediaType.parse("text/plain"), AZUtils.getUserId(this));
Call call = client.editUser(AZUtils.getToken(this), fbody, name, id);
call.enqueue(new Callback() {
    @Override
    public void onResponse(retrofit.Response response, Retrofit retrofit) {
        AZUtils.printObject(response.body());
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
});


是的,我认为这是一个问题(https://github.com/square/retrofit/issues/1063)与改造2.0,你可能想坚持1.9
看到我的编辑,我还没有尝试过,欢迎您
@Bhargav您可以将界面更改为`@Multipart @POST("/ api/Accounts/editaccount")调用 editUser(@PartMap Map params);`并且当您有文件时:`Map map = new HashMap <>(); RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpg"),file); map.put("file \"; filename = \""+ file.getName(),fileBody);`
@insomniac是的我刚刚发现了这一点,也可以使用`MultiPartBody.Part`

2> jimmy0251..:

有一种正确的方法可以上传名称为Retrofit 2的文件,没有任何黑客攻击:

定义API接口:

@Multipart
@POST("uploadAttachment")
Call uploadAttachment(@Part MultipartBody.Part filePart); 
                                   // You can add other parameters too

像这样上传文件:

File file = // initialize file here

MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), RequestBody.create(MediaType.parse("image/*"), file));

Call call = api.uploadAttachment(filePart);

这仅演示了文件上传,您还可以使用@Part注释在同一方法中添加其他参数.


我们如何使用MultipartBody.Part发送多个文件?

3> Samuel Ivan..:

我为我的注册用户使用了Retrofit 2.0,从注册帐户发送multipart/form文件图像和文本

在我的RegisterActivity中,使用AsyncTask

//AsyncTask
private class Register extends AsyncTask {

    @Override
    protected void onPreExecute() {..}

    @Override
    protected String doInBackground(String... params) {
        new com.tequilasoft.mesasderegalos.dbo.Register().register(txtNombres, selectedImagePath, txtEmail, txtPassword);
        responseMensaje = StaticValues.mensaje ;
        mensajeCodigo = StaticValues.mensajeCodigo;
        return String.valueOf(StaticValues.code);
    }

    @Override
    protected void onPostExecute(String codeResult) {..}

在我的Register.java类中,使用Retrofit进行同步调用

import android.util.Log;
import com.tequilasoft.mesasderegalos.interfaces.RegisterService;
import com.tequilasoft.mesasderegalos.utils.StaticValues;
import com.tequilasoft.mesasderegalos.utils.Utilities;
import java.io.File;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call; 
import retrofit2.Response;
/**Created by sam on 2/09/16.*/
public class Register {

public void register(String nombres, String selectedImagePath, String email, String password){

    try {
        // create upload service client
        RegisterService service = ServiceGenerator.createUser(RegisterService.class);

        // add another part within the multipart request
        RequestBody requestEmail =
                RequestBody.create(
                        MediaType.parse("multipart/form-data"), email);
        // add another part within the multipart request
        RequestBody requestPassword =
                RequestBody.create(
                        MediaType.parse("multipart/form-data"), password);
        // add another part within the multipart request
        RequestBody requestNombres =
                RequestBody.create(
                        MediaType.parse("multipart/form-data"), nombres);

        MultipartBody.Part imagenPerfil = null;
        if(selectedImagePath!=null){
            File file = new File(selectedImagePath);
            Log.i("Register","Nombre del archivo "+file.getName());
            // create RequestBody instance from file
            RequestBody requestFile =
                    RequestBody.create(MediaType.parse("multipart/form-data"), file);
            // MultipartBody.Part is used to send also the actual file name
            imagenPerfil = MultipartBody.Part.createFormData("imagenPerfil", file.getName(), requestFile);
        }

        // finally, execute the request
        Call call = service.registerUser(imagenPerfil, requestEmail,requestPassword,requestNombres);
        Response bodyResponse = call.execute();
        StaticValues.code  = bodyResponse.code();
        StaticValues.mensaje  = bodyResponse.message();
        ResponseBody errorBody = bodyResponse.errorBody();
        StaticValues.mensajeCodigo  = errorBody==null
                ?null
                :Utilities.mensajeCodigoDeLaRespuestaJSON(bodyResponse.errorBody().byteStream());
        Log.i("Register","Code "+StaticValues.code);
        Log.i("Register","mensaje "+StaticValues.mensaje);
        Log.i("Register","mensajeCodigo "+StaticValues.mensaje);
    }
    catch (Exception e){
        e.printStackTrace();
    }
}
}

在RegisterService的界面中

public interface RegisterService {
@Multipart
@POST(StaticValues.REGISTER)
Call registerUser(@Part MultipartBody.Part image,
                                @Part("email") RequestBody email,
                                @Part("password") RequestBody password,
                                @Part("nombre") RequestBody nombre
);
}

对于Utilities解析的InputStream响应

public class Utilities {
public static String mensajeCodigoDeLaRespuestaJSON(InputStream inputStream){
    String mensajeCodigo = null;
    try {
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(
                    inputStream, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line).append("\n");
        }
        inputStream.close();
        mensajeCodigo = sb.toString();
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }
    return mensajeCodigo;
}
}



4> Muhammad Wal..:

更新Retrofit2.0中图像文件上传的代码

public interface ApiInterface {
    @Multipart
    @POST("user/signup")
    Call updateProfilePhotoProcess(@Part("email") RequestBody email, @Part("password") RequestBody password, @Part("profile_pic\"; filename=\"pp.png\" ") RequestBody file);
}

更改MediaType.parse("image/*")MediaType.parse("image/jpeg")

RequestBody reqFile = RequestBody.create(MediaType.parse("image/jpeg"), file);
RequestBody email = RequestBody.create(MediaType.parse("text/plain"), "upload_test4@gmail.com");
RequestBody password = RequestBody.create(MediaType.parse("text/plain"), "123456789");

Call call = apiService.updateProfilePhotoProcess(email,password,reqFile);
call.enqueue(new Callback() {
    @Override
    public void onResponse(Call call, Response response) {
        String TAG = response.body().toString();

        UserModelResponse userModelResponse = response.body();
        UserModel userModel = userModelResponse.getUserModel();

       Log.d("MainActivity","user image = "+userModel.getProfilePic());

    }

    @Override
    public void onFailure(Call call, Throwable t) {
        Toast.makeText(MainActivity.this,""+TAG,Toast.LENGTH_LONG).show();

    }
});



5> Anjana Sharm..:

添加@insomniac给出的答案.您可以创建一个Map用于放置RequestBody包含图像的参数.

接口代码

public interface ApiInterface {
@Multipart
@POST("/api/Accounts/editaccount")
Call editUser (@Header("Authorization") String authorization, @PartMap Map map);
}

Java类的代码

File file = new File(imageUri.getPath());
RequestBody fbody = RequestBody.create(MediaType.parse("image/*"), file);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), firstNameField.getText().toString());
RequestBody id = RequestBody.create(MediaType.parse("text/plain"), AZUtils.getUserId(this));

Map map = new HashMap<>();
map.put("file\"; filename=\"pp.png\" ", fbody);
map.put("FirstName", name);
map.put("Id", id);
Call call = client.editUser(AZUtils.getToken(this), map);
call.enqueue(new Callback() {
@Override
public void onResponse(retrofit.Response response, Retrofit retrofit) 
{
    AZUtils.printObject(response.body());
}

@Override
public void onFailure(Throwable t) {
    t.printStackTrace();
 }
});



6> duggu..:

因此,这是完成任务的非常简单的方法。您需要按照以下步骤操作:-

1.第一步

public interface APIService {  
    @Multipart
    @POST("upload")
    Call upload(
        @Part("item") RequestBody description,
        @Part("imageNumber") RequestBody description,
        @Part MultipartBody.Part imageFile
    );
}

您需要按进行整个通话@Multipart requestitem并且image number是被包裹在刚刚绳体RequestBody。我们使用的MultipartBody.Part class,使我们除了发送带有请求的二进制文件数据外,还可以发送实际的文件名

2.第二步

  File file = (File) params[0];
  RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);

  MultipartBody.Part body =MultipartBody.Part.createFormData("Image", file.getName(), requestBody);

  RequestBody ItemId = RequestBody.create(okhttp3.MultipartBody.FORM, "22");
  RequestBody ImageNumber = RequestBody.create(okhttp3.MultipartBody.FORM,"1");
  final Call request = apiService.uploadItemImage(body, ItemId,ImageNumber);

现在您拥有了image path,您需要转换为file.Now转换fileRequestBodyusing方法RequestBody.create(MediaType.parse("multipart/form-data"), file)。现在,您需要将转换RequestBody requestFileMultipartBody.Partusing方法MultipartBody.Part.createFormData("Image", file.getName(), requestBody);

ImageNumber并且ItemId是我需要发送到服务器的另一个数据,因此我也将两者都放入了RequestBody

欲了解更多信息

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有