HttpClient 上传文件接口报错“missing content

问题描述:
同事在使用.4.1版本上传文件时,接口报错“ -type ” 。找我过来一起分析原因 。部分代码如下:
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、是什么?有什么作用?
官方解析:
当-type为/form-data类型时,需要用指定分隔符 。所以后面跟的随机数,就是分隔符,后端就是通过解析到的值作为分隔符来分隔参数的 。
想必大家和我一样看到这段解析时,也是不太理解 。既然是来分割参数的,参数是在里 。那么我们来看下.()方法的源码,看看能不能找到答案 。
private final AbstractMultipartForm multipart;@Overridepublic void writeTo(final OutputStream outstream) throws IOException {this.multipart.writeTo(outstream);}
可以看到调用的是m.()

HttpClient 上传文件接口报错“missing content

文章插图
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(final OutputStream out) throws IOException {doWriteTo(out, true);}void doWriteTo(final OutputStream out,final boolean writeContent) throws IOException {final ByteArrayBuffer boundaryEncoded = encode(this.charset, this.boundary);for (final FormBodyPart part: getBodyParts()) {writeBytes(TWO_DASHES, out);writeBytes(boundaryEncoded, out);writeBytes(CR_LF, out);//以--boundaryEncoded\r\n为分割符分割多个文件或键值对formatMultipartHeader(part, out);writeBytes(CR_LF, out);if (writeContent) {part.getBody().writeTo(out);}writeBytes(CR_LF, out);}// 以--boundaryEncoded\r\n为分割符 结束writeBytes(TWO_DASHES, out);writeBytes(boundaryEncoded, out);writeBytes(TWO_DASHES, out);writeBytes(CR_LF, out);}
从上面源码可知作为分割符,将请求的输出流分割开 。
就是当http请求-Type为/form-data时,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开 。既可以上传键值对,也可以上传文件 。当上传的字段是文件时,会有-Type来表名文件类型 。
由于有隔离,所以/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件 。
经过上面的分析,我们知道就是在-Type为/form-data的情况下,作为一个随机数分隔符,来实现既可以上传多个文件,也可以上传键值对 。
2、那么问题来了,是如何产生的呢?
大家可能会想到,我自己生成一个行不行:
uploadFile.setHeader("Content-Type", "multipart/form-data;----ba77f35b192c8918628309c77e6add06");