java http 文件上传原理_HTTP文件上传原理

本文详细介绍了HTTP文件上传的原理,包括POST请求的格式、multipart/form-data的使用,以及服务器端如何解析请求内容。通过示例代码展示了Servlet处理文件上传的过程,并提到了使用FileUpload组件简化文件上传操作的方法。文章强调了服务器端解析请求的重要性,并提供了一个简单的FileUploadDemo程序作为总结。
摘要由CSDN通过智能技术生成

前言

对于这块知识点,我一直都是模糊的,不是非常清楚的。在平时的工作中,遇到上传的问题,也没有深入的去研究过,也都是直接用别人封装好的类来完成自己的工作。某一天,看了本书,说到这个知识点,一脸茫然,觉的有必要去深入的学习一下,至少要让自己明白HTTP文件上传的过程,这个原理,以便将来出现问题,也能通过原理进行深入的分析,而不是等问题来了,两眼一抹黑,然后漫无目的的百度。哦,如果是那样子,那该是多么的痛苦,多么的无助。

所以查缺补漏,以免让将来的自己感到无助、痛苦,甚至难堪,走起!!!

HTTP上传原理

我们在开发的时候,当要用到文件上传功能时,前端开发人员都会告诉你以下几条金科律令:

提交方式必须为post;

表单中有文件上传的表单项必须为;

必须指定表单类型enctype="multipart/form-data"。

是的,我们必须按照上面这三条铁令进行设定,否则就无法上传文件。比如我们一般会这么写:

上传用户:

上传文件1:

上传文件2:

我这里写了一个简单的Servlet:

@WebServlet("/UploadServletDemo")

public class UploadServletDemo extends HttpServlet{

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

request.setCharacterEncoding("utf-8");

// 获取表单(POST)数据

ServletInputStream in = request.getInputStream();//此方法得到所有的提交信息,不仅仅只有内容

// 转换流

InputStreamReader inReaser = new InputStreamReader(in);

// 缓冲流

BufferedReader reader = new BufferedReader(inReaser);

String str = null;

while ((str=reader.readLine()) != null){

System.out.println(str);

}

}

}

我们把程序跑起来,然后通过Fiddler进行抓包,可以看到我们发送的Post请求中,请求体中有以下这样的数据:

POST http://localhost:8080/javawebservlet_war/UploadServletDemo HTTP/1.1

Host: localhost:8080

Connection: keep-alive

Content-Length: 446

Cache-Control: max-age=0

Origin: http://localhost:8080

Upgrade-Insecure-Requests: 1

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqj67FUBQUHXZj78G

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

Referer: http://localhost:8080/javawebservlet_war/

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,und;q=0.7,zh-TW;q=0.6

Cookie: JSESSIONID=6BE280EF3CBE213F73430FFDF015DE97

------WebKitFormBoundaryqj67FUBQUHXZj78G

Content-Disposition: form-data; name="username"

abc

------WebKitFormBoundaryqj67FUBQUHXZj78G

Content-Disposition: form-data; name="file1"; filename="文件1.txt"

Content-Type: text/plain

ABC文件1

------WebKitFormBoundaryqj67FUBQUHXZj78G

Content-Disposition: form-data; name="file2"; filename="文件2.txt"

Content-Type: text/plain

BDF文件2

------WebKitFormBoundaryqj67FUBQUHXZj78G--

到这里,我们就大概就知道了HTTP上传文件的原理了。HTTP把需要上传的表单的所有数据按照一定的格式存放在请求体中,对于文件也是同样的。

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqj67FUBQUHXZj78G表示要上传附件,其中boundary表示分隔符,如果表单中有多项,就要使用boundary进行分隔,每个表单项由------FormBoundary开始,以------FormBoundary结尾。例如这样:

------FormBoundary

Content-Disposition: form-data; name="param1"

value1

------FormBoundary

这个boundary的值是由浏览器生成的,由浏览器来保证与上传内容不重复。在每个分隔项里,需要我们去重点关注Content-Disposition消息头,其中第一个参数总是固定不变的form-data,name表示表单元素属性名,回车换行符后面的内容就是元素的值。还有Content-Type表示我们上传的文件的MIME类型,我们在服务器端需要根据这个进行文件的区分。

HTTP就是按照这种格式,把表单中的数据封装成一个请求一股脑的发给服务器端,服务器端根据这种规则对接收到的请求进行解析,从而完成文件上传功能。

最后一个boundary的结尾会多两个--

FileUpload组件

通过上面的描述,我们可以知道完成文件上传功能,重点工作不是在于客户端,而是在于服务器端。服务器端需要根据客户端发送过来的请求,根据上面说的规则对请求报文进行解析,从而提取出上传的文件内容。可以看到,虽然上面的规则比较简单,但是用不同的开发语言来一次性写出没有Bug的解析程序,也不是那么简单的。而且这种实现过一遍,就可以大家共享的东西就非常适合开发成组件供大家一起使用,所以呢,开源社区就开发了这样的一个组件,这个组件来给我们完成了上面规则的编码,而我们需要做的就是去学会使用这个组件,就这么简单!

下面就通过一个简单的FileUploadDemo程序来总结一下如何使用FileUpload组件。

FileUpload Demo

下面来一段简单的使用Demo。

@WebServlet("/FileUpload")

public class FileUploadDemo extends HttpServlet {

@Override

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

DiskFileItemFactory fac = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(fac);

upload.setFileSizeMax(10 * 1024 * 1024);

upload.setSizeMax(20 * 1024 * 1024);

if (upload.isMultipartContent(request)) {

try {

List list = upload.parseRequest(request);

for (FileItem item : list) {

if (item.isFormField()) {

String fileName = item.getFieldName();

String value = item.getString("UTF-8");

System.out.println(fileName + ":" + value);

} else {

String name = item.getName();

String id = UUID.randomUUID().toString();

name = id + name;

String realPath = getServletContext().getRealPath("/upload");

File file = new File(realPath, name);

item.write(file);

item.delete();

}

}

} catch (Exception e) {

e.printStackTrace();

}

} else {

System.out.println("不处理!");

}

}

}

总结

这篇文章对通过HTTP协议进行文件上传原理进行了比较详细的分析和总结,希望对大家有帮助!

果冻想,认真玩技术的地方。

2019年7月31日 于内蒙古呼和浩特。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值