Http文件传输

Http请求报文结构

http request message分四段:

request-line
headers
空行
entity-body

1. request-line+headers 即QQ浏览器F12里的 请求标头,是描述段,描述报文的各种属性,便于浏览器解析

request-line:

请求 POST / HTTP/1.1

其中POST是请求方法(method),/是请求uri即地址,HTTP/1.1是本次通信所采用的协议版本,此例中是采用HTTP 1.1版本
org.apache.http中获取request-line:

RequestLine requestline=request.getRequestLine();

获取请求方法:

requestline.getMethod();

获取请求地址:

requestline.getUri();

获取协议版本:

requestline.getProtocolVersion();

headers:

Accept text/html, application/xhtml+xml, /
Referer http://192.168.1.107:1234/
Accept-Language zh-Hans-CN,zh-Hans;q=0.5
User-Agent Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko QQBrowser/8.2.4258.400
Content-Type application/x-www-form-urlencoded
Accept-Encoding gzip, deflate
Host 192.168.1.107:1234
Content-Length 40
Connection Keep-Alive
Cache-Control no-cache:

org.apache.http中获取headers无论是整体还是部分都是在entity的方法中实现,也就是说要先获取entity才行
获取entity:

HttpEntity entity=request.getEntity();

获取content-type:

entity.getContentType();

在post form data的时候,content-type中还包含了boundary的信息,作为分割线用于服务器辨识entity中的多段数据。
org.apache.http中获取boundary:

String contentType=inentity.getContentType().getValue();
String boundary=contentType.substring(contentType.indexOf("=")+1);
boundary="--"+boundary;

2. entity-body是数据段,即QQ浏览器F12里的 请求正文,报文主体,承载要传递的信息。
post的表单数据位于此。例如post字符串“无比牛逼”,new是input控件的名字

new=%E6%97%A0%E6%AF%94%E7%89%9B%E9%80%BC

request 和response都继承了http massage的格式,都包含body,也就都可以包含entity。

读取文件使用HTML 5 File API

如何把文件读取到内存,使用HTML 5新推出的File API。
获取文件对象

var file = document.getElementById('fileToUpload').files[0];

获取文件大小、名字、类型

file.size
file.name
file.type

读取文件内容,使用FileReader对象,这是一个工具类,包含了多种读取文件内容的方法。
新建一个FileReader对象

var reader = new FileReader(); 

File API中对FileReader的介绍


发送文件使用XMLHttpRequest

HTML 5的File API 读取文件后并无发送方法,还需一种方法把读取的文件信息post出去,普通的表单控件只能发送输入框内的字符串,接受不了文件信息,XMLHttpRequest于是上场,这哥们既能发送也能接受HTTP报文,这里只用发送功能。
XMLHttpRequest的介绍在此
其方法介绍在此
例子在此

abort()
取消当前响应,关闭连接并且结束任何未决的网络活动。
这个方法把 XMLHttpRequest 对象重置为 readyState 为 0 的状态,并且取消所有未决的网络活动。例如,如果请求用了太长时间,而且响应不再必要的时候,可以调用这个方法。
getAllResponseHeaders()
把 HTTP 响应头部作为未解析的字符串返回。
如果 readyState 小于 3,这个方法返回 null。否则,它返回服务器发送的所有 HTTP 响应的头部。头部作为单个的字符串返回,一行一个头部。每行用换行符 “\r\n” 隔开。
getResponseHeader()
返回指定的 HTTP 响应头部的值。其参数是要返回的 HTTP 响应头部的名称。可以使用任何大小写来制定这个头部名字,和响应头部的比较是不区分大小写的。
该方法的返回值是指定的 HTTP 响应头部的值,如果没有接收到这个头部或者 readyState 小于 3 则为空字符串。如果接收到多个有指定名称的头部,这个头部的值被连接起来并返回,使用逗号和空格分隔开各个头部的值。
open()
初始化 HTTP 请求参数,例如 URL 和 HTTP 方法,但是并不发送请求。
send()
发送 HTTP 请求,使用传递给 open() 方法的参数,以及传递给该方法的可选请求体。
setRequestHeader()
向一个打开但未发送的请求设置或添加一个 HTTP 请求。


HTTP文件传输的编码过程

request-line中不允许出现汉字,用utf-8进行编码。例如请求下载”小苹果伴奏mp3“时,request-line为

GET /storage/emulated/0/lisa/%E5%B0%8F%E8%8B%B9%E6%9E%9C%E4%BC%B4%E5%A5%8F.mp3 HTTP/1.1

其中uri为

/storage/emulated/0/lisa/%E5%B0%8F%E8%8B%B9%E6%9E%9C%E4%BC%B4%E5%A5%8F.mp3

小苹果伴奏五个字被写成了utf-8码。
服务器使用uri查询文件时,utf-8码不能辨识,需要转化为中文字符串,

String uri=requestline.getUri();
uri=URLDecoder.decode(uri,"utf-8");

HTTP相关故障

POST后无响应,被挂起
POST之后浏览器自动刷新页面(地址不变,即request url不变),和和GET一样需要指定response的内容,如果没有指定response的内容,则会被挂起。

网页下载文件过程中请求被挂起后连接被人为中断,退出lisa所有记录清空,并无法再次连接
手机内存中的RecordBase被破坏,lisa退出时自动保存RecordBase清零;再次连接时被手机系统阻止。

网页上传文件后,服务器接受到文件,但是体积比源文件大,而且无法正常打开文件
可以试上传htm文件,如果发现服务器接受到的文件首尾有多余内容,可以判服务器创建文件保存了多余的信息。
这里写图片描述


如何让PC浏览器作为文件管理器(client),访问android手机(server)?

此功能类似FTP,但是用HTTP实现,因为android没有原生库支持FTP。
需要用到FileEntity这个类

httpRequestHandler是个接口,其handler函数的request参数是httprequest,不能直接提取entity,只有httpEntityEnclosingRequest才能使用getEntity()来提取Entity。前者是后者的父类。所以必须先判断一下request类型,看看是否是此类型的Request,然后转换成httpEntityEnclosingRequest并使用getEntity()方法提取。参考此文。

如何处理下载链接,让浏览器直接下载而不是打开链接?参考此文

response.addHeader("Content-Disposition", "attachment");//指明链接应下载而非打开
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章