原文链接:https://blog.csdn.net/wsdtq123/article/details/78888734

POST上传文件

最早的HTTP POST是不支持文件上传的,给编程开发带来很多问题。但是在1995年,ietf出台了rfc1867,也就是《RFC 1867 -Form-based File Upload in HTML》,用以支持文件上传。所以Content-Type的类型扩充了multipart/form-data用以支持向服务器发送二进制数据。因此发送post请求时候,表单<form>属性enctype共有二个值可选,这个属性管理的是表单的MIME编码:
 ①application/x-www-form-urlencoded(默认值)
 ②multipart/form-data
其实form表单在你不写enctype属性时,也默认为其添加了enctype属性值,默认值是enctype="application/x- www-form-urlencoded".

用multipart/form-data上传文件

今天我们主要谈谈使用httpclient以multipart/form-data来实现文件上传。
multipart/form-data的请求头必须包含一个特殊的头信息:Content-Type,且其值也必须规定为multipart/form-data,同时还需要规定一个内容分割符用于分割请求体中的多个post的内容,如文件内容和文本内容自然需要分割开来,不然接收方就无法正常解析和还原这个文件了。具体的头信息如下:Content-Type: multipart/form-data; boundary=${bound}
其中${bound} 是一个占位符,--${bound}代表我们规定的分割符,可以自己任意规定,但为了避免和正常文本重复了,尽量要使用复杂一点的内容,通常由客户端自主生成,如占位符为:yurnnlukjwfbrdiqvnqnegfitaaddkom,则分隔符为:--yurnnlukjwfbrdiqvnqnegfitaaddkom

一个真实的请求体

一个真实的请求体大致如下:
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="Filename" 2.jpg
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="pictitle" 2.jpg
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="dir" upload1
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="fileNameFormat" {time}{rand:6}
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="fileName" 2.jpg
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="upfile"; filename="2.jpg"
Content-Type: application/octet-stream ÿØÿàJFIFÿÛC $.' ",#(7),01444'9=82<.342ÿÛC 2!!22222222222222222222222222222222222222222222222222ÿÀ22"ÿÄÿÄ3!1Aa"Qq¡Á2BR#3¢±ÿÄÿÄ !13QAÿÚ?ÇÛ{çZ3ãçjãêµrÖåcñ÷·µO åÃKë¥Tv®ÊhíI§~2,ºFT4É÷åò©Ëë¹¢Y¼9 etúÍD=ÞØâ¡1Mº :î~þõStY)vè°l¦t¶
îðâHùË=E>ÿ¤R3µ³/îEæÞb¿¸Í §\6£O­J#4Ý÷åFÀÕh_E5âw¢§ßg®÷1V¯/­Å·Ô³nDÞ=9ÏÒªi ,xïS^
2Ûx¦ÊF²åÐåHûÒ¬±}K;h×ZóøÂîïÝÐàx®Z4]©
¦àr_Ç-yç½q4Ó2FVÎÀáïåì\Ó¯á×%½6[=Pë9lëÔcJcæ;-²½Ø'ÒPÝÈË5ÉÎ=´©%¶·ÜFc«1%±Û'SL?´íã8¢¶y@zc^]»Tm8·Ss"É1æQwGË'þÔ
Á¢ÊQçYµmÁÐýim<mk9b]ç¡ç^Uðã}MxB8bÛÆk`·ÃÈãw?í\¥º7sÆ¢Ù~i9·&ÞÖÍ #Õ»èF:{Ò6Ûfç¡°à2érj§{âÝðÞâ[ 'u×ãD>clä4§
H35ÕÛlÅp4=¥,·(íA~xçO~]êjW
Òªçók­gëæ%¼lª&27ër[áL¤ñÌr7¦II?¹4©`Q^Í,$¤gw9î(¬ÃùÝÆSþTØÿ쯨]?WÞ«¾%b¯C]EVÊÎoþÂ:Ùê¦î,¨>¡Ìw¢Ô0K
7£ô.¬:TÒ${B0ª
1E¢æUãÉéôïEQ ÿÙ
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="Upload"
Submit Query
--yurnnlukjwfbrdiqvnqnegfitaaddkom--
请求体以--yurnnlukjwfbrdiqvnqnegfitaaddkom--结束,其中乱码部分为上传的文件流。
HttpClient使用multipart/form-data来上传文件

封装的方法:

public static String postFileMultiPart(String url,Map<String,ContentBody> reqParam) throws ClientProtocolException, IOException{
CloseableHttpClient httpclient = HttpClients.createDefault(); try {
// 创建httpget.
HttpPost httppost = new HttpPost(url); //setConnectTimeout:设置连接超时时间,单位毫秒。setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。setSocketTimeout:请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。
RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(15000).build();
httppost.setConfig(defaultRequestConfig); System.out.println("executing request " + httppost.getURI()); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
for(Entry<String,ContentBody> param : reqParam.entrySet()){
multipartEntityBuilder.addPart(param.getKey(), param.getValue());
}
HttpEntity reqEntity = multipartEntityBuilder.build();
httppost.setEntity(reqEntity); // 执行post请求.
CloseableHttpResponse response = httpclient.execute(httppost); System.out.println("got response"); try {
// 获取响应实体
HttpEntity entity = response.getEntity();
//System.out.println("--------------------------------------");
// 打印响应状态
//System.out.println(response.getStatusLine());
if (entity != null) {
return EntityUtils.toString(entity,Charset.forName("UTF-8"));
}
//System.out.println("------------------------------------");
} finally {
response.close(); }
} finally {
// 关闭连接,释放资源
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}

调用postMultipart

String url = "xxxxxxx";
String httpRes = null;
String localFileName = "E:/2.jpg"; Map<String,ContentBody> reqParam = new HashMap<String,ContentBody>();
reqParam.put("Filename", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
reqParam.put("pictitle", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
reqParam.put("dir", new StringBody("upload1", ContentType.MULTIPART_FORM_DATA));
reqParam.put("fileNameFormat", new StringBody("{time}{rand:6}", ContentType.MULTIPART_FORM_DATA));
reqParam.put("fileName", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
reqParam.put("fileName", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
reqParam.put("upfile", new FileBody(new File(fileLocation)));
reqParam.put("Upload", new StringBody("Submit Query", ContentType.MULTIPART_FORM_DATA)); httpRes = HttpClientUtil.postFileMultiPart(url,reqParam);

  

利用httpclient上传文件需要两点:
1.这里一定不能有httppost.addHeader("Content-Type","multipart/form-data; boundary=yurnnlukjwfbrdiqvnqnegfitaaddkom"); 因为这里面有个boundary参数属性是不可控的。这个值是由浏览器生成的。如果强行指明和可能导致边界值不一致 就会请求失败 详细参见 http://blog.csdn.net/xiaojianpitt/article/details/6856536
2.StringBody的ContentType是multipart/form-data
HttpClientUtil工具类
附HttpClientUtil工具类,https://gitee.com/qigugu/dsb-capture-image/blob/master/src/main/java/com/dsb/util/HttpClientUtil.java

  

(十)HttpClient以multipart/form-data上传文件的更多相关文章

  1. 前端 - jquery方式 / iframe +form 方式 上传文件

    环境与上一章一样 jquery 方式上传文件: HTML代码 {#html代码开始#} <input type="file" id="img" > ...

  2. python中使用multipart/form-data请求上传文件

    最近测试的接口是上传文件的接口,上传单个文件,我主要使用了2种方法~ 接口例如: URL: http://www.baidu.com/*** method:post 参数: { "salar ...

  3. Unable to find ‘struts.multipart.saveDir’ Struts2上传文件错误的解决方法

    Unable to find ‘struts.multipart.saveDir’ Struts2上传文件错误的解决方法 在使用struts2的项目中上传文件的时候出现了一个这样的错误: 2011-7 ...

  4. 使用python或robotframework调multipart/form-data接口上传文件

    这几天调一个multipart/form-data类型的接口,遇到点小阻碍.之前同事有使用urllib库写了个类似的方法实现,比较长,想要改的时候发现不太好使.在网上查找发现用requests库做这个 ...

  5. django Form组件 上传文件

    上传文件 注意:FORM表单提交文件要有一个参数enctype="multipart/form-data" 普通上传: urls: url(r'^f1/',views.f1), u ...

  6. 笔谈HTTP Multipart POST请求上传文件

    公司一做iOS开发的同事用HTTP Multipart POST请求上传语音数据,但是做了两天都没搞定,项目经理找到我去帮忙弄下.以前做项目只用过get.post,对于现在这个跟服务器交互的表单请求我 ...

  7. form 为什么上传文件enctype现场

    FORM要素enctype属性指定表单数据server当提交所使用的编码类型,默认默认值它是"application/x-www-form-urlencoded". 这样的编码方式 ...

  8. [转载红鱼儿]Delphi实现微信开发(3)如何使用multipart/form-data格式上传文件

    开始前,先看下要实现的微信接口,上传多媒体文件,这个接口是用Form表单形式上传的文件.对我来说,对http的Form表单一知半解,还好,查到这个资料,如果你也和我一样,必须看看这篇文章. 在xali ...

  9. 《手把手教你》系列技巧篇(五十四)-java+ selenium自动化测试-上传文件-中篇(详细教程)

    1.简介 在实际工作中,我们进行web自动化的时候,文件上传是很常见的操作,例如上传用户头像,上传身份证信息等.所以宏哥打算按上传文件的分类对其进行一下讲解和分享. 2.为什么selenium没有提供 ...

  10. 《手把手教你》系列技巧篇(五十五)-java+ selenium自动化测试-上传文件-下篇(详细教程)

    1.简介 在实际工作中,我们进行web自动化的时候,文件上传是很常见的操作,例如上传用户头像,上传身份证信息等.所以宏哥打算按上传文件的分类对其进行一下讲解和分享. 2.为什么selenium没有提供 ...

随机推荐

  1. ShoneSharp语言(S#)的设计和使用介绍系列(9)— 一等公民“函数“爱炫巧

    ShoneSharp语言(S#)的设计和使用介绍 系列(9)— 一等公民“函数“爱炫巧 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/Shon ...

  2. SPL常用迭代器

    ArrayIterator 熟悉使用seek()跳过元素 熟悉使用asort,ksort排序 <?php $fruits = array( 'apple'=>'apple value', ...

  3. OpenStack的Trove组件详解

    一:简介     一.背景 1. 对于公有云计算平台来说,只有计算.网络与存储这三大服务往往是不太够的,在目前互联网应用百花齐放的背景下,几乎所有应用都使用到数据库,而数据库承载的往往是应用最核心的数 ...

  4. python的转义

    print('"I\'m OK"') print("I'm OK") print('"I"\'m \"OK"') &qu ...

  5. Java IO(十四) CharArrayReader 和 CharArrayWriter

    Java IO(十四) CharArrayReader 和 CharArrayWriter 一.介绍 CharArrayReader 和 CharArrayWriter 是字符数组输入流和字符数组输出 ...

  6. OAuth + Security -1 - 认证服务器配置

    配置 基础包依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId&g ...

  7. Beta冲刺 —— 5.29

    这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.展示了每个人当天的成果. ...

  8. Rocket - debug - DebugCustomXbar

    https://mp.weixin.qq.com/s/7h9Bdb0x4_clyigMU_0B7Q 讨论DebugCustomXbar中的几个问题. 1. sources/sourceParams n ...

  9. Java实现 蓝桥杯 算法提高 字符串匹配

    试题 算法提高 字符串匹配 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符:当选项关闭时 ...

  10. Java实现十六进制转十进制

    基础练习 十六进制转十进制 时间限制:1.0s 内存限制:512.0MB 提交此题 锦囊1 锦囊2 问题描述 从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出. 注:十六进 ...