HttpClient使用MultipartEntityBuilder上传文件时乱码问题解决

HttpClient使用MultipartEntityBuilder是常用的上传文件的组件,但是上传的文件名称是乱码,一直输出一堆的问号:

 

HttpClient使用MultipartEntityBuilder上传文件时乱码问题解决_第1张图片

如何解决呢?废话少说,先直接上代码:

 public static String doPostWithFiles(HttpClient httpClient, String url, Map params, Map files) throws IOException {
        HttpPost method = new HttpPost(url);
        ContentType contentType = ContentType.create("multipart/form-data", Charset.forName("UTF-8"));
        MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532)
                .setCharset(Charset.forName("UTF-8"))
                .setContentType(contentType);
        files.forEach((fileName, file) -> builder.addBinaryBody(fileName, file, ContentType.MULTIPART_FORM_DATA, fileName));
        params.forEach((name, value) -> builder.addTextBody(name, String.valueOf(value), contentType));

        method.setEntity(builder.build());
        try {
            HttpResponse response = httpClient.execute(method);
            int sc = response.getStatusLine().getStatusCode();
            if (sc != HttpServletResponse.SC_OK) {
                LOG.warn("doPostWithFiles fail| statusCode=" + sc + ", params=" + params.toString());
                return null;
            }
            return EntityUtils.toString(response.getEntity(), Consts.UTF_8);
        } catch (Exception e) {
            LOG.warn("PointsClient | do Post service HttpException Exception", e);
            throw e;
        } finally {
            method.releaseConnection();
        }
    }

这是整个方法的完整实现,

在测试的时候参考了这里的部分内容使用HttpClient MultipartEntityBuilder 上传文件,并解决中文文件名乱码问题_12934784的技术博客_51CTO博客

但是仍然不能解决问题。

最后只能自己理解源码,来研究如何做。

比较关键的是这两行,本来params的foreach是这么写的:

  files.forEach((fileName, file) -> builder.addBinaryBody(fileName, file, ContentType.MULTIPART_FORM_DATA, fileName));
        params.forEach((name, value) -> builder.addTextBody(name, String.valueOf(value), ContentType.MULTIPART_FORM_DATA));

files.forEach这一行明显是上传文件的而params.forEach是用来传递参数的。问题就出在params里的中文成了乱码。

经过debug发现,经过foreach之后,builder里的参数的字符集都是Consts.ISO_8859_1,很明显这应该就是问题所在,那研究一下MULTIPART_FORM_DATA就非常必要了。我们看一下源码:

  static {
        APPLICATION_ATOM_XML = create("application/atom+xml", Consts.ISO_8859_1);
        APPLICATION_FORM_URLENCODED = create("application/x-www-form-urlencoded", Consts.ISO_8859_1);
        APPLICATION_JSON = create("application/json", Consts.UTF_8);
        APPLICATION_OCTET_STREAM = create("application/octet-stream", (Charset)null);
        APPLICATION_SVG_XML = create("application/svg+xml", Consts.ISO_8859_1);
        APPLICATION_XHTML_XML = create("application/xhtml+xml", Consts.ISO_8859_1);
        APPLICATION_XML = create("application/xml", Consts.ISO_8859_1);
        MULTIPART_FORM_DATA = create("multipart/form-data", Consts.ISO_8859_1);
        TEXT_HTML = create("text/html", Consts.ISO_8859_1);
        TEXT_PLAIN = create("text/plain", Consts.ISO_8859_1);
        TEXT_XML = create("text/xml", Consts.ISO_8859_1);
        WILDCARD = create("*/*", (Charset)null);
        DEFAULT_TEXT = TEXT_PLAIN;
        DEFAULT_BINARY = APPLICATION_OCTET_STREAM;
    }

可以看到,这里的字符集全都是Consts.ISO_8859_1,要么就没设置,因此果断直接改一下:

  ContentType contentType = ContentType.create("multipart/form-data", Charset.forName("UTF-8"));
然后:
 params.forEach((name, value) -> builder.addTextBody(name, String.valueOf(value), ContentType.MULTIPART_FORM_DATA));

至此,问题解决。

你可能感兴趣的:(java,服务器,前端)