问题描述:
同事在使用HttpClient4.4.1版本上传文件时,接口报错“missing content-type boundary”。找我过来一起分析原因。部分代码如下:
HttpPut uploadFile = new HttpPut(uri);
uploadFile.setHeader("Authorization", "");
uploadFile.setHeader("Content-Type", "multipart/form-data");
uploadFile.setHeader("Ocp-Apim-Subscription-Key", key);
uploadFile.setHeader("Authorization", bearer);
//HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
multipartEntityBuilder.addBinaryBody("file",new FileInputStream(uploadFile), ContentType.APPLICATION_OCTET_STREAM,uploadFile.getName());
HttpEntity httpEntity = multipartEntityBuilder.build();
httpPut.setEntity(httpEntity);
// 设置请求超时
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(2000).build();
httpPut.setConfig(requestConfig);
// 发送请求
CloseableHttpResponse response = httpClient.execute(httpPut);
问题处理:
经过网上一顿分析查找,网上说把
//uploadFile.setHeader("Content-Type", "multipart/form-data");
这行代码注释掉就可以。我们一试,果然接口成功调用。
问题分析:
想必大家都和我有同样的疑问:为什么注释掉那行代码就可以了?
1、boundary是什么?有什么作用?
官方解析:
当content-type为multipart/form-data类型时,需要用boundary指定分隔符。所以boundary后面跟的随机数,就是分隔符,后端就是通过解析到boundary的值作为分隔符来分隔参数的。
想必大家和我一样看到这段解析时,也是不太理解。既然boundary是来分割参数的,参数是在Entity里。那么我们来看下MultipartFormEntity.writeTo()方法的源码,看看能不能找到答案。
private final AbstractMultipartForm multipart;
@Override
public void writeTo(final OutputStream outstream) throws IOException {
this.multipart.writeTo(outstream);
}
可以看到调用的是AbstractMultipartForm.doWriteTo()
private static final ByteArrayBuffer CR_LF = encode(MIME.DEFAULT_CHARSET, "\r\n");
private static final ByteArrayBuffer TWO_DASHES = encode(MIME.DEFAULT_CHARSET, "--");
public void writeTo(fina