ps :本文仅参考
对于较大的文件我们可以直接用FTP协议传文件,较小的文件则可以向B / S 一样用HTTP上传。
首先,由于要传文件,我们需要用 POST 来发送数据。GET 有长度限制,而且数据跟在URL后面。
既然要发送POST请求,我们先来看看POST 请求的报文格式。
HTTP 报文介绍
先写一个简单的Html 页面发送一个表单来观察它发出的POST 报文,表单中包含一个上传的文件和文件描述的文本。
- <!DOCTYPE HTML>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>文件上传</title>
- </head>
- <body>
- <form method="post" enctype="multipart/form-data" action="http://www.baidu.com/form">
- <input type="file" name="file">
- <input type="text" name="description"
- <br />
- <input type="reset" value="reset">
- <input type="submit" value="submit">
- </form>
- </body>
- </html>
在Chrom 上的报文格式如下:
- POST /form HTTP/1.1
-
- p; Host: www.baidu.com
- Connection: keep-alive
- Content-Length: 2417
- Cache-Control: max-age=0
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- Origin: null
- Upgrade-Insecure-Requests: 1
- User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
- Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryM4LGQcTCCIBilnPT
- Accept-Encoding: gzip, deflate
- Accept-Language: zh-CN,zh;q=0.8
- Cookie: BAIDUID=9A110F7F907AEAC501CD156DDE0EA380:FG=1
-
- ------WebKitFormBoundaryM4LGQcTCCIBilnPT
- Content-Disposition: form-data; name="file"; filename="close.png"
- Content-Type: image/png
- 这里包括了图片的二进制数据
- nbsp;------WebKitFormBoundaryM4LGQcTCCIBilnPT
- Content-Disposition: form-data; name="description"
- This is a image
- ------WebKitFormBoundaryM4LGQcTCCIBilnPT--
HTTP报文由三个部分组成
:对报文进行描述的起始行(start line),包含属性的首部(header)块,以及可选的、包含数据的主体(body)部分。
请求报文的起始行格式为<method> <request-URL> <version>
method :为客户端希望服务器对资源进行的动作,一般为GET、POST、HEAD等。
请求URL:为资源的绝对路径,这里是表单Action决定的。
版本:保报文所使用的Http 版本,如1.1 ,1.0。
HTTP 首部块
可以有零个或多个首部,每个首部都包含一个名字,后面跟着一个冒号( : ),然后是一个可选的空格,接着是一个值,最后是一个CRLF( /r/n )。首部是由一个空行(CRLF)结束的。表示了首部列表的结束和实体主体部分的开始。在自己构造报文时一定要注意加换行和空行,以免造成格式错误。在HTTP 1.1 中,要求有效的请求或响应中必须包含特定的首部。请求首部如下:
- Host: www.baidu.com
- Connection: keep-alive
- Content-Length: 2417
- Cache-Control: max-age=0
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
- Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryM4LGQcTCCIBilnPT
- Accept-Encoding: gzip, deflate
- Accept-Language: zh-CN,zh;q=0.8
简单解释一下几个首部:
Host:接收请求的服务器地址
Connection:允许客户端和服务器指定与请求/响应连接有关的选项,Keep-alive 表示持久连接
Content-Length:实体主体的大小,这个在构造报文的时候一定要设置
CacheControl:控制缓存的行为
Accept:用户代理可处理的媒体类型
User-Agent:HTTP客户端程序的信息,浏览器的信息
Content-Type:实体主体的媒体类型,表单中有文件上传应设置为multipart/form-data。boundary 很重要,这是一个识别文件流的边界,用来标识文件开始和结尾的位置。
Accept-Encoding:是浏览器发给服务器,声明浏览器支持的编码类型
Accept-Language声明浏览器支持的语言
HTTP 数据主体
这部分为HTTP要传输的内容。
开始的boundary 就是在Content-Type中设置的值,boundary用于作为请求参数之间的界限标识,在多个参数之间要有一个明确的界限,这样服务器才能正确的解析到参数。它有格式要求,开头必须是--,不同的浏览器产生的boundary也不同,但前面都要有-- 。
Content-Disposition就是当用户想把请求所得的内容存为一个文件的时候提供一个默认的文件名。
中间的就是我们传输的数据了。
最后还要加上一个boundary--,不要忘记最后的--。
这样报文就构造结束了。