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");//指明鏈接應下載而非打開
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章