【问题标题】:Upload picture to server using retrofit 2使用改造 2 将图片上传到服务器
【发布时间】:2018-01-23 20:03:40
【问题描述】:

首先让我们看一下代码:

public interface ApiInterface {
    @Multipart
    @POST("my/files/photo/")
    Call<FileUploadResponse> uploadPhoto(@Header("authorization") String auth,
                                     @Part MultipartBody.Part file,
                                     @Part("file-type") RequestBody fileType);
}

我是这样调用这个接口的:

RequestBody body = RequestBody.create(MediaType
            .parse(getContentResolver().getType(fileUri)), file);
MultipartBody.Part avatarBody = MultipartBody.Part
            .createFormData(data, file.getName(), body);
RequestBody fileType = RequestBody.create(
            MediaType.parse("text/plain"), "profile");
client.uploadPhoto(getToken(), avatarBody, fileType);

我从服务器收到“未提供文件类型”的响应。如果我像这样在 uploadPhoto 函数上更改文件和文件类型的位置:

@Multipart
@POST("my/files/photo/")
Call<FileUploadResponse> uploadPhoto(@Header("authorization") String auth,
                                 @Part("file-type") RequestBody fileType
                                 @Part MultipartBody.Part file);

我收到“未提供文件”的响应。 我用我自己写在 JS 上的代码检查了服务器:

<!DOCTYPE html>
<script language="JavaScript" type="text/javascript" src="C://Users/User/Downloads/jquery-3.2.1.min.js"></script>

<form action="">
  <input type="text" name="authorize" id="authorize">
  <br>
  <input type="file" name="photo" accept="image/*" id="filechooser" onchange="onFileChange(this)" >
  <br>
  <input value="profile" type="text" name="file-type" id="type">
  <br>
  <input type="button" onclick="uploadFile()">
</form>


<script>
var blobFile;
function onFileChange(ss) {
	blobFile = ss.files[0];
	alert(blobFile);
}
function uploadFile() {

	var storedJWT = $('#authorize').val();
	var fileType = $('#type').val();
    var formData = new FormData();
    formData.append("file-type", fileType);
	formData.append("photo", blobFile);
	console.log(storedJWT);
    $.ajax({
       url: "url",
       type: "POST",
       data: formData,
	   headers: {
        authorization: storedJWT
	   },
       processData: false,
       contentType: false,
       success: function(response) {
		   console.log(response);
       },
       error: function(jqXHR, textStatus, errorMessage) {
           console.log(errorMessage);
       }
    });
}</script>

一切正常。 JS 生成请求的脚本如下:

Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
authorization:JWT token
Connection:keep-alive
Content-Length:67601
Content-Type:multipart/form-data; boundary=----
WebKitFormBoundary3MtpMA70hG41luF1
Host:localhost
------WebKitFormBoundary3MtpMA70hG41luF1
Content-Disposition: form-data; name="file-type"

profile
------WebKitFormBoundary3MtpMA70hG41luF1
Content-Disposition: form-data; name="photo"; filename="1231231313.jpg"
Content-Type: image/jpeg


------WebKitFormBoundary3MtpMA70hG41luF1--

改造请求是:

Content-Type: multipart/form-data; boundary=238182ad-d99c-4d44-9ba6-7d178a14b2e9
Content-Length: 59776
authorization: JWT token
--238182ad-d99c-4d44-9ba6-7d178a14b2e9
Content-Disposition: form-data; name="photo"; filename="1502703422332.jpg"
Content-Type: image/jpeg
Content-Length: 59369
//bytes
--238182ad-d99c-4d44-9ba6-7d178a14b2e9
Content-Disposition: form-data; name="file-type"
Content-Transfer-Encoding: binary
Content-Type: text/plain; charset=utf-8
Content-Length: 7
profile
--238182ad-d99c-4d44-9ba6-7d178a14b2e9--

我不明白哪里可能出错...

【问题讨论】:

    标签: android-studio retrofit2 okhttp3


    【解决方案1】:

    经过多次搜索,我发现服务器没有处理像

    这样的标头
    Content-Transfer-Encoding: binary
    Content-Type: text/plain; charset=utf-8
    

    我必须从我的请求中删除这些标头。解决方案是在我的 API 接口中创建上传功能,如下所示:

    @POST("my/files/photo/")
        Call<FileUploadResponse> uploadPhoto(@Header("Content-Type") String contentType,
                                              @Header("Authorization") String auth,
                                              @Body MultipartBody body);
    

    并像这样调用这个函数:

    ApiClient.ApiInterface client = ApiClient.getClient();
    File file = new File(getPathFromUri(fileUri));
    RequestBody fileBody = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
    MultipartBody body = new MultipartBody.Builder().addFormDataPart("file-type", "profile")
                    .addFormDataPart("photo", "image.png", fileBody)
                    .build();
    client.uploadPhoto("multipart/form-data; boundary=" + body.boundary(),
                        PrefManager.getInstance().getToken(), body);
    

    结果我收到以下请求:

    Content-Type: multipart/form-data; boundary=27ec8d66-d29d-48aa-a2fe-08c6664b10c7
    Content-Length: 56412
    Authorization: JWT token
    --27ec8d66-d29d-48aa-a2fe-08c6664b10c7
    Content-Disposition: form-data; name="file-type"
    Content-Length: 7
    profile
    --27ec8d66-d29d-48aa-a2fe-08c6664b10c7
    Content-Disposition: form-data; name="photo"; filename="image.png"
    Content-Type: image/jpeg
    Content-Length: 56089
    /* bytes */
    --27ec8d66-d29d-48aa-a2fe-08c6664b10c7--
    

    而且效果很好。

    【讨论】:

      猜你喜欢
      • 2021-11-29
      • 2020-04-04
      • 2018-10-05
      • 2016-08-02
      • 2017-11-25
      • 1970-01-01
      • 2018-10-10
      • 2019-02-14
      • 1970-01-01
      相关资源
      最近更新 更多