java - 在 PartMap 中使用 Retrofit 和 WebKitFormBoundary 将文件发送到服务器

标签 java android retrofit okhttp

我有一个由 postman 生成的查询,用于将文件和一些信息发送到我的服务器。它在我的程序中运行良好。

  MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
        RequestBody body = RequestBody.create(mediaType,
                "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"C:\\testFile.doc\"\r\nContent-Type: application/msword\r\n\r\n\r\n" +
                        "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"id\"\r\n\r\n7\r\n" +
                        "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\n3\r\n" +
                        "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"note\"\r\n\r\nafejhejfh\r\n" +
                        "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"list[0][id]\"\r\n\r\n1\r\n" +
                        "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"list[0][is_checked]\"\r\n\r\n0\r\n" +
                        "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"list[0][filename]\"; filename=\"C:\\test.pdf\"\r\nContent-Type: application/pdf\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");

改造方法:

@Headers({"Accept: application/json", "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"})
@POST("api/save")
Call<SaveResponse> save(@Header("Authorization") String authorization,
                                   @Body RequestBody map);

第一次遇到webkitformboundary,需要将上面的示例更改为动态创建的Partmap。因为需要在一个循环中从另一个列表中添加一些参数。 我尝试使用下面的示例生成零件图,并将“WebKitFormBoundary7MA4YWxkTrZu0gW”添加到 api 文档中编写的 header 中

  --header 'Authorization: {{authorization}}' \
  --header 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \

下面的代码从服务器返回422错误

查询 map 。

Map<String, RequestBody> requestMap = new HashMap<>();

RequestBody file = null;
if (file != null) {
    file = RequestBody.create(MediaType.parse("application/msword"), testFile);
    requestMap.put("filename", file);
}

RequestBody id = RequestBody.create(MediaType.parse("text/plain"), "18");
RequestBody type = RequestBody.create(MediaType.parse("text/plain"), "3");
RequestBody notes = RequestBody.create(MediaType.parse("text/plain"), notesTextArea.getText());
RequestBody list0id = RequestBody.create(MediaType.parse("text/plain"), "1");
RequestBody list0is_checked = RequestBody.create(MediaType.parse("text/plain"), "0");


RequestBody pdfFilename = null;
if (pdfFile != null) {
    pdfFilename  = RequestBody.create(MediaType.parse("application/pdf"), pdfFile);
    requestMap.put("list[0][filename]", pdfFilename );
}

requestMap.put("file", file);
requestMap.put("id", id);
requestMap.put("type", type);
requestMap.put("notes", notes);
requestMap.put("list[0]id", list0id);
requestMap.put("list[0]is_checked", list0is_checked);

改造方法:

  @Multipart
    @Headers({"Accept: application/json", "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"})
    @POST("api/save")
    Call<SaveResponse> save(@Header("Authorization") String authorization,
                                       @PartMap Body map);

因此需要任何帮助来了解如何将 WebKitFormBoundary7MA4YWxkTrZu0gW 和其他所需信息放入我的 Partmap 中。

预先感谢您的帮助

附:编码员新年快乐)

最佳答案

所以我通过这种方式解决这个问题

向我的服务器发出请求。没有 header “content-type:multipart/form-data;boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW”的请求,API 文档中对此进行了描述。

 @Multipart
    @Headers({"Accept: application/json"})
    @POST("api/save")
    Call<SaveResponse> save(@Header("Authorization") String authorization,
                                       @PartMap Map<String, RequestBody> map,
                                       @Part List<MultipartBody.Part> files);

动态填写我们的查询

  private void fillQuery() {

        fileListPart = new ArrayList<>();
        MultipartBody.Part filePart = null;
        if (mainFile != null) {
            if (mainFile.getName().endsWith(".pdf")) {
                filePart = MultipartBody.Part.createFormData("filename", mainFile.getName(), RequestBody.create(MediaType.parse("application/pdf"), mainFile));
            } else if (mainFile.getName().endsWith(".doc") || mainFile.getName().endsWith(".docx")) {
                filePart = MultipartBody.Part.createFormData("filename", mainFile.getName(), RequestBody.create(MediaType.parse("application/msword"), mainFile));
            }
            fileListPart.add(filePart);
        }

        requestBodyMap = new HashMap<>();
        RequestBody id = RequestBody.create(MediaType.parse("text/plain"), "id");
        RequestBody type = RequestBody.create(MediaType.parse("text/plain"), "type");
        RequestBody notes = RequestBody.create(MediaType.parse("text/plain"), "notes");

        requestBodyMap.put("id", id);
        requestBodyMap.put("type", type);
        requestBodyMap.put("notes", notes);

        for (int i = 0; i < dynamicCollectionWirhParameters.size(); i++) {
            String prefix = "list[";
            String checkIdParameter = "][id]";
            String checkIsCheckedParameter = "][is_checked]";
            String checkFileParameter = "][filename]";

            RequestBody checklist_id = RequestBody.create(MediaType.parse("text/plain"), "2");//id
            RequestBody is_checked = RequestBody.create(MediaType.parse("text/plain"), "1"); // server convert 1 and 0 to boolean value
            requestBodyMap.put(prefix + i + checkIdParameter, checklist_id);
            requestBodyMap.put(prefix + i + checkIsCheckedParameter, is_checked);

            if (dynamicCollectionFileCollection.get(i) != null) {
                File tempFile = dynamicCollectionFileCollection.get(i);
                filePart = null;
                if (tempFile.getName().endsWith(".pdf")) {
                    filePart = MultipartBody.Part.createFormData(prefix + i + checkFileParameter, dynamicCollectionFileCollection.get(i).getName(), RequestBody.create(MediaType.parse("application/pdf"), dynamicCollectionFileCollection.get(i)));
                } else if (dynamicCollectionFileCollection.get(i).getName().endsWith(".doc") || dynamicCollectionFileCollection.get(i).getName().endsWith(".docx")) {
                    filePart = MultipartBody.Part.createFormData(prefix + i + checkFileParameter, dynamicCollectionFileCollection.get(i).getName(), RequestBody.create(MediaType.parse("application/msword"), dynamicCollectionFileCollection.get(i)));
                }
                fileListPart.add(filePart);
            }
        }

    }

并将我们的数据发送到服务器

private void saveDatas() {
        fillQuery();

        Call<SaveResponse> sendDatasCall = DependenciesStorage.getRetrofitService().save(
                DependenciesStorage.getAuthorizationKey(),
                requestBodyMap, fileListPart);

        sendDatasCall.enqueue(new Callback<SaveResponse>() {
            @Override
            public void onResponse(Call<SaveResponse> call, Response<SaveResponse> response) {
                if (response.isSuccessful()) {

                  } else {

                 }
            }

            @Override
            public void onFailure(Call<SaveResponse> call, Throwable throwable) {
            }
        });

    }

看起来很容易)但我花了将近两天才找到它

关于java - 在 PartMap 中使用 Retrofit 和 WebKitFormBoundary 将文件发送到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48042641/

相关文章:

java - 无法使用 jSoup 发布

java - 尝试将背景从白色更改为黑色,但无法运行此 timer() 方法,屏幕只有白色

retrofit - 无法为 io.reactivex.Observable 创建调用适配器

android - 改造 + GSON 解串器

java - Java EE 服务器上的 Exec 运行时

java - 如何强制 gradle 不下载依赖项(而是从缓存加载它们)?

java - 如何检查变量是 double 型还是字符串型

android - 来自 xml 的 NavigationView onClick 导致错误

android-应用内计费

android - 在android中使用Base64改造图像上传