收藏
回答

服务端上传文件到云存储提示not well-formed multipart/form-data?

AppID
wxbfd52ca8da22670f

服务端上传文件到云存储分两步: 1、获取上传链接 2、上传文件 如官方说明所述https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-http-api/storage/uploadFile.html

我在第二步时遇到报错 The body of your POST request is not well-formed multipart/form-data. 请大侠支招!

代码如下

主文件
String fileName = path.getFileName().toString();
String cloudPath = "shenqitest/" + fileName;

WxCloudUploadFileResult uploadResult = cloudService.uploadFile(this.env, cloudPath);
System.out.println(uploadResult.toString());
Map<String, File> fileParams = new HashMap<>();
fileParams.put("file", path.toFile());

Map<String, String> otherParams = new HashMap<>();
otherParams.put("key", cloudPath);
otherParams.put("Signature", uploadResult.getAuthorization());
otherParams.put("x-cos-security-token", uploadResult.getToken());
otherParams.put("x-cos-meta-fileid", uploadResult.getCosFileId());
//
//Map<String, String> headerParams = new HashMap<>();
//headerParams.put("Content-Type", "multipart/form-data"); // 不加boundary会报错: The specified method is not allowed against this resource.

String resp = HTTPUtils.uploadFile(uploadResult.getUrl(), fileParams, otherParams, null);


工具文件
public static String uploadFile(String url, Map<String, File> fileParams, Map<String, String> otherParams, Map<String, String> headerParams) {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    String result = "";
    try {
        HttpPost httpPost = new HttpPost(url);
        //设置请求头
        if (headerParams != null && headerParams.size() > 0) {
            for (Map.Entry<String, String> e : headerParams.entrySet()) {
                String value = e.getValue();
                String key = e.getKey();

                if (StringUtils.isNotBlank(value)) {
                    httpPost.setHeader(key, value);
                }
            }
        }
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.setCharset(StandardCharsets.UTF_8);
        //builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//加上此行代码解决返回中文乱码问题
        // 文件传输http请求头(multipart/form-data)
        if (fileParams != null && fileParams.size() > 0) {
            for (Map.Entry<String, File> e : fileParams.entrySet()) {
                String fileParamName = e.getKey();
                File file = e.getValue();
                if (file != null) {
                    //String fileName = URLEncoder.encode(file.getName(), StandardCharsets.UTF_8);
                    String fileName = file.getName();
                    //try (InputStream stream = new FileInputStream(file)) { // 请求时要用stream
                        builder.addBinaryBody(fileParamName, new FileInputStream(file), ContentType.APPLICATION_OCTET_STREAM, fileName);
                    //}
                }
            }
        }
        // 普通参数请求头(application/json)
        ContentType contentType = ContentType.create(ContentType.APPLICATION_JSON.getMimeType(), StandardCharsets.UTF_8);
        if (otherParams != null && otherParams.size() > 0) {
            for (Map.Entry<String, String> e : otherParams.entrySet()) {
                String value = e.getValue();
                if (StringUtils.isNotBlank(value)) {
                    builder.addTextBody(e.getKey(), value, contentType);
                }
            }
        }
        HttpEntity entity = builder.build();
        httpPost.setEntity(entity);

        CloseableHttpResponse response = httpClient.execute(httpPost);
        HttpEntity responseEntity = response.getEntity();
        if (responseEntity != null) {
            // 将响应内容转换为字符串
            result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            httpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return result;
}

要传的文件是jpeg,文件的ContentType试过APPLICATION_OCTET_STREAM、IMAGE_JPEG、MULTIPART_FORM_DATA、DEFAULT_BINARY,其它参数的ContentType试过DEFAULT_TEXT、MULTIPART_FORM_DATA、APPLICATION_JSON,都是一样的结果

回答关注问题邀请回答
收藏

2 个回答

  • 子言
    子言
    07-18

    换了一种访问方式,解决了

    public static org.apache.http.HttpResponse sendMultiFormMixData(String url, Map<String, File> nameFiles,
                                                                    List<NameValuePair> otherParams, List<NameValuePair> headerParams) {
        HttpPost httpPost = new HttpPost(url);
        //设置请求头
        if (headerParams != null && headerParams.size() > 0) {
            for (NameValuePair pair : headerParams) {
                String key = pair.getName();
                String value = pair.getValue();
                if (StringUtils.isNotBlank(value)) {
                    httpPost.setHeader(key, value);
                }
            }
        }
    
        // 设置传输参数,设置编码。设置浏览器兼容模式,解决文件名乱码问题
        MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
    
        // 解决中文字符?的问题
        ContentType contentTypeText = ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), StandardCharsets.UTF_8);
        for (NameValuePair pair : otherParams) {
            builder.addPart(pair.getName(), new StringBody(pair.getValue(), contentTypeText));
        }
    
        // 解决中文文件名?的问题
        ContentType contentTypeForm = ContentType.create(ContentType.MULTIPART_FORM_DATA.getMimeType(), StandardCharsets.UTF_8);
        for (Map.Entry<String, File> nameFile : nameFiles.entrySet()) {
            File file = nameFile.getValue();
            if (file.exists()) {
                ContentBody fileBody = new FileBody(file, contentTypeForm);
                builder.addPart(nameFile.getKey(), fileBody);
            } else {
                log.warn("跳过不存在的文件: {}", file.getPath());
            }
        }
    
        HttpEntity httpEntity = builder.build();
        httpPost.setEntity(httpEntity);
    
        try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
            return client.execute(httpPost);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    07-18
    有用
    回复
  • Mr.Zhao
    Mr.Zhao
    发表于移动端
    07-18
    新手用resttemplate或者wxjava-sdk
    07-18
    有用
    回复 1
    • 子言
      子言
      07-18
      谢谢
      07-18
      回复
登录 后发表内容
问题标签