Http multipart/form-data多参数Post方式上传数据
2016-12-08 20:25
721 查看
关于multipart/form-data格式的上传,网上有大量的解决文章,这里,我们使用HttpURLConnection 来完成
感谢以下文章作者提供的解决方法http://www.cnblogs.com/zyzl/p/4526914.html
http://topmanopensource.iteye.com/blog/16 4000
05238
这里,我们碰到的问题主要是如何上传一个文件,同时上传一个其他参数。当我们向后台发送数据时(只有字符串(String)参数时),服务器会收到以下这种信息
POST /test HTTP/1.1 Accept-Language: zh-CN,zh;q=0.8 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Content-Type: multipart/form-data; boundary=--HrOGHuIjDhR_gtUesEBnpWxVp9JH209p Cache-Control: no-cache Pragma: no-cache Host: localhost Connection: keep-alive Content-Length: 224 --HrOGHuIjDhR_gtUesEBnpWxVp9JH209p Content-Disposition: form-data; name="keyword" test --HrOGHuIjDhR_gtUesEBnpWxVp9JH209p Content-Disposition: form-data; name="submit" Convert --HrOGHuIjDhR_gtUesEBnpWxVp9JH209p--
如果是向服务器发送一个文件(图片),会收到类似以下信息
POST /test HTTP/1.1 Accept: text/plain, */* Accept-Language: zh-cn Host: localhost Content-Type:multipart/form-data;boundary=--testsssssss User-Agent: WinHttpClient Content-Length: 3693 Connection: Keep-Alive -------------------------------7db372eb000e2 Content-Disposition: form-data; name="file"; filename="kn.jpg" Content-Type: image/jpeg (此处省略jpeg文件二进制数据...) -------------------------------7db372eb000e2--
协议头看不懂没有关系,我们模仿着写就可以了(文章最下方有我们拼接的协议格式)。
从以上两条数据中,我们可以发现,数据的传输过程中,只要遵循以上的格式发送请求就可以了,资料中介绍,在上传给服务器的数据中,不是所有的协议头内容都需要说明的。
content-type是必须的,它包括一个类似标志性质的名为boundary的标志,它可以是随便输入的字符串。
以下 我们贴一段代码,来解释其中的内容
public static class FileImageUpload { private static final int TIME_OUT = 100000; //超时时间 private static final String CHARSET = "utf-8"; //编码格式 public static final String FAILURE = "FAILURE"; /** * android上传文件到服务器 * * @param filePath 需要上传的文件的目录 * @param RequestURL 请求的rul * @return 返回响应的内容 */ public static String uploadFile(String RequestURL, String filePath, String postValue) { //生成一个文件 File file = new File(filePath); //边界标识 随机生成,这个作为boundary的主体内容 String BOUNDARY = UUID.randomUUID().toString(); String PREFIX = "--"; //回车换行,用于调整协议头的格式 StringLINE_END = "\r\n"; //格式的内容信息 String CONTENT_TYPE = "multipart/form-data"; try { URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时时间 conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); //允许输入流 conn.setDoInput(true); //允许输出流 conn.setDoOutput(true); //不允许使用缓存 conn.setUseCaches(false); //请求方式 conn.setRequestMethod("POST"); //设置编码 utf-8 conn.setRequestProperty("Charset", CHARSET); //设置为长连接 conn.setRequestProperty("connection", "keep-alive"); //这里设置请求方式以及boundary的内容,即上面生成的随机字符串 conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); if (file != null) { //当文件不为空,把文件包装并且上传 //这里定义输出流,用于之后向服务器发起请求 OutputStream outputSteam = conn.getOutputStream(); DataOutputStream dos = new DataOutputStream(outputSteam); //这里的StringBuffer 用来拼接我们的协议头 StringBuffer sb = new StringBuffer(); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"postKey\"" + LINE_END+LINE_END); sb.append(postValue + LINE_END); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); /** * 这里重点注意: * name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件 * filename是文件的名字,包含后缀名的 比如:abc.png */ sb.append("Content-Disposition: form-data; name=\"postKey\"; filename=\"" + file.getName() + "\"" + LINE_END); //这里Content-Type 传给后台一个mime类型的编码字段,用于识别扩展名 sb.append("Content-Type: image/png; charset=" + CHARSET + LINE_END); sb.append(LINE_END); dos.write(sb.toString().getBytes()); InputStream is = new FileInputStream(file); byte[] bytes = new byte[1024]; int len = 0; while ((len = is.read(bytes)) != -1) { dos.write(bytes, 0, len); } is.close(); dos.write(LINE_END.getBytes()); byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes(); dos.write(end_data); dos.flush(); /** * 获取响应码 200=成功 * 当响应成功,获取响应的流 */ int res = conn.getResponseCode(); //获取后台返回的数据 if (res == 200) { BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; StringBuffer sb_result = new StringBuffer(); while ((line = bufferedReader.readLine()) != null) { sb_result.append(line); } return sb_result.toString(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return FAILURE; } }
上面的代码中,StringBuffer拼接出来并且流输出的内容就是下面的内容
--(boundary的任意字符串)********** Content-Disposition: form-data; name="postKey" postValue --(boundary的任意字符串)********** Content-Disposition: form-data; name="postKey"; filename="file.getName()" Content-Type: image/png; charset=utf-8 (文件的二进制数据) --(boundary的任意字符串)**********--
代码中需要注意的几个地方,这里我们如果需要传递多个值,只需要用boundary的字符串按照上面的形式分开就可以了,然后,在传递普通字符串值的时候,name=”postKey”之后需要两次回车换行,这个问题目前不清楚是服务器导致的还是数据传输过程中会出现的问题导致的。
在传输文件数据的过程中,请求过程中postKey由服务器端指定传值内容。在下面一行字段中,Content-Type中,传递的类型,应该是用于识别扩展名的,按照mime的标准传递。
相关文章推荐
- spring mvc源码-》MultipartReques类-》主要是对文件上传进行的处理,在上传文件时,编码格式为enctype="multipart/form-data"格式,以二进制形式提交数据,提交方式为post方式。
- WebAPI通过multipart/form-data方式同时上传文件以及数据(含HttpClient上传Demo)
- WebAPI通过multipart/form-data方式同时上传文件以及数据(含HttpClient上传Demo)
- Multipart/form-data POST文件上传详解 理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下: <form me
- WebAPI通过multipart/form-data方式同时上传文件以及数据(含HttpClient上传Demo)
- WebAPI通过multipart/form-data方式同时上传文件以及数据(含HttpClient上传Demo)
- http以post方式上传一个文件,构造其请求头和消息报文 application/x-www-form-urlencoded multipart/form-data
- java httpclient multipart/form-data 方式post
- struts中post方式上传文件,enctype="multipart/form-data",request.getParameter("file") 是null的问题分析
- HTTP协议之post multipart/form-data数据类型实例
- HttpWebRequest post "multipart/form-data"类型的web数据
- http multipart/form-data POST文件上传详解
- android向服务器上传multipart/form-data文件(upload using multipart post using httpclient in android)
- 四种常见的 POST 提交数据方式(application/x-www-form-urlencoded,multipart/form-data,application/json,text/xml)
- HTTP AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式
- HTTP multipart/form-data 上传方式说明
- struts2开发环境中,enctype="multipart/form-data"上传文件时,request.getInputStream()为null的原因(转http://topic.csdn.net/u/20101210/11/78454a19-7
- 简单解决 multipart/form-data 文件上传表单中 传递参数无法获取的办法! (解决办法:动态更改表单提交URL)
- Multipart/form-data POST文件上传详解
- enctype="multipart/form-data" 文件上传,获取form 表单参数的问题