javaWeb文件上传报文分析

来源:互联网 发布:seo全网优化指南 pdf 编辑:程序博客网 时间:2024/09/21 09:25

起初我使用javaweb文件上传采用SpringMVC+ajaxFileUpload插件,由于底层封装了太多,所以我研究了一下文件上传的基本原理和Http协议的报文分析。

一.浏览器部分封装请求报文

由于http协议有get请求和post请求两种方式,所以用户上传的变量和信息可以存储在请求头中也可单独以键值对存储在请求体中。由于文件上传文件体积比较大,所以采用post请求方式,将文件流写在请求体中。由于大部分文件上传不要跳转页面,属于后台程序,所以可以使用ajax在后台开辟线程发送报文,也可以使用form标签浏览器自动封装的方法发出报文,最终希望生成的目标报文如下:

        RequestHeaders:

  1. POST /FileUpload/fileUpload HTTP/1.1
  2. Host: 127.0.0.1:8080
  3. Connection:keep-alive
  4. Content-Length: 1847861
  5. Accept: */*
  6. Origin: http://127.0.0.1:8080
  7. X-Requested-With: XMLHttpRequest
  8. User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
  9. Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryRdIys56kU7nV6fja
  10. Referer: http://127.0.0.1:8080/FileUpload/index.jsp
  11. Accept-Encoding: gzip, deflate
  12. Accept-Language: zh-CN,zh;q=0.8
  13. Cookie: JSESSIONID=D7644C944581DFDE49A6DAAF77CA77DA
RequestPayload:
  1. ------WebKitFormBoundaryRdIys56kU7nV6fja
  2. Content-Disposition: form-data; name="file"; filename="app-debug.rar"
  3. Content-Type: application/octet-stream

  4. ------WebKitFormBoundaryRdIys56kU7nV6fja--
以上报文是我文件上传成功后打开浏览器F12-network 得到成功文件上传的报文。由于http协议是以键值对封装消息,但是上传的文件是二进制流,所以采用在请求体中上传文件不是以文件名 文件流键值对出现,加上需要知道上传文件名,表单元素名,所以采用boundary为分界线分割每个文件,所以这个报文中比较重要的是Content-Type,不能使用常用的application/www-urlencoding 而应该设置为multipart/formdata 并声明使用的boundary。
构造以上的报文有两种办法:
1.使用formdata构造并使用ajax请求
使用j-Query-1.7-min.js版本 的ajax请求。
<form id="fileupload">
    <input type="file"  id="file" name="file" multiple="mul
tiple"  />
    </form>
前端元素标签设定,设置file标签的multiple可实现多文件上传
var formdata=new FormData($("#fileupload")[0]);
$.ajax({
url:basePath+"fileUpload",
type:"POST",
data:formdata,
contentType:false,
cache:false,
async:false,
processData:false,
success:function(){
alert("success");
}
});
这里最关键的是ajax processData和contentType的设定,processData表示处理过程会将请求体封装成键值对,与我们的报文不符合,所以设定processData为false,
contentType设定为false表明设置请求头中的contentType为指定的multipart、
2.使用浏览器form标签自己封装的方法
<form action="<%=basePath%>/fileUpload" method="post" enctype="multipart/form-data">
    <input type="text" name="user" value=""/><br>
    <input type="file" name="password" multiple="multiple" />   
    <input type="submit" value="提交" />
    </form>
由于使用的不是ajax会导致整个页面的跳转。这里设置enctype属性可以自动构造Content-Type请求头实现报文打印

二.javaweb后台解析报文取出文件体
由于涉及到大量字符串操作,故导入api 可以使用基本上传组件commons-fileupload-1.2.1.jar和commons-io-1.4.jar两个jar包具体实现过程可参考fileupload上传组件使用方法。如果不使用组件,上传文件相关信息存放在请求体中,只能使用request getInputStream截取到对应的流并分析解析出对应的文件。不可以使用request getParameter getParameter方法只能获取到上传报文中请求体对应的键值对信息。

0 0