文件上传下载,说来悲剧。
以前都是用的ADF\OAF\JALOR等框架开发,SE搭好工程,只负责业务逻辑开发,基本没怎么想过为什么。
直到一天,为了防止系统入侵,做文件上传现在过滤拦截,才想到一个问题。我们上传下载的原理到底是什么?一直再copy代码,为什么要这么做哪?
我们用一个servlet去处理一个上传文件,看下代码很简单,基本是从request读取流,然后通过IO写入到指定目录,或者通过一些中间件写入一些分布式文件平台。
那么文件是怎么序列化为流数据分装在HTTP报文中的哪?
其实我们的文件上传怎么都要经历如下链路:
1、浏览器解析文件,打包成数据流。
2、通过管道和服务器连接,通过http传输数据到后台。
3、java程序(也可能是其他程序)做IO处理,做文件写操作。
浏览器上传文件原理
<form action="servlet/UploadFile" method="post"
enctype="multipart/form-data">
<input type="file" name="fileUpload" id="fileUpload" />
<input type="submit" value="上传" />
</form>
enctype:属性规定在发送到服务器之前应该如何对表单数据进行编码。
form表单中enctype属性可以用来控制对表单数据的发送前的如何进行编码,
enctype有三种,分别为:
multipart/form-data不对字符编码,用于发送二进制的文件,其他两种类型不能用于发送文件;
text/plain用于发送纯文本内容,空格转换为 “+” 加号,不对特殊字符进行编码,一般用于email之类的;
application/x-www-form-urlencoded,在发送前会编码所有字符,即在发送到服务器之前,所有字符都会进行编码(空格转换为 “+” 加号,"+"加号转换为空格,特殊符号转换为 ASCII HEX 值)。
其中application/x-www-form-urlencoded为默认类型。
看下文件上传的报文,就这么一个file控件,以CSDN上传头像为例,浏览器会自动把上传文件解析如下:
Request URL: https://me.csdn.net/api/user/uploadBase64Avatar
Request Method: POST
Status Code: 200
Remote Address: 39.96.132.69:443
Referrer Policy: unsafe-url
access-control-allow-credentials: true
access-control-allow-headers: Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Data-Type,X-Requested-With
access-control-allow-methods: GET,PUT,POST,DELETE,OPTIONS
access-control-allow-origin: https://i.csdn.net
content-type: application/json; charset=UTF-8
date: Sun, 13 Oct 2019 09:26:34 GMT
server: openresty
status: 200
Provisional headers are shown
Accept: application/json, text/javascript, /; q=0.01
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryV5ocEPiRQuRh2vcB
Origin: https://i.csdn.net
Referer: https://i.csdn.net/
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
avatar_file: (binary)
a:
最下面是POST请求封装的Form Data,我们会发现浏览器有自动把数据解析成二进制的数据的功能。
具体数据如下:
------WebKitFormBoundaryV5ocEPiRQuRh2vcB
Content-Disposition: form-data; name=“avatar_file”; filename=“avatar_file.png”
Content-Type: image/png
‰PNG
IHDR––<qâ IDATx^ì½”]gy.ü|»ï}z›3]Ó$z±%[–{ƒÁ—Ä6¡òJnˆ —rC
……………………………………………………
------WebKitFormBoundaryV5ocEPiRQuRh2vcB
Content-Disposition: form-data; name=“a”
------WebKitFormBoundaryV5ocEPiRQuRh2vcB–
中间内容省略
二、服务器
1.服务器端程序收到"multipart/form-data"类型的http请求消息
2.读取这个请求消息里面的实体内容
3.解析每个分区的数据
4.从每个分区中解析出描述头和主体内容部分