最近在開發一個ASP.NET程式要讓用戶可以直接下載檔案時,伺服器不必實際產生一個實體路徑,而是把資料庫中的二進位資料,
透過Response.BinaryWrite(或Response.OutStream)的方式,產生至HttpResponse中讓用戶直接下載下來。
這樣的作法,可以用於常見的檔案,例如:Word/PowerPoint檔、文字檔、圖片等。
然而,這樣的網頁程式在一般網頁上是可以正常運作的,但換到Mobile平台運作時,完全就不是這麼一回事了。
那到底差異在那些地方呢?跟著該篇文章下的標題,很清楚的說明就是在Android的內鍵瀏覽器出現了問題。
根據目前測試下來的結果,Windows Phone(含Windows Mobile)、Opera Mobile/Mini、iPhone與Android(Firefox)是可以正常運作的,
使用過去熟悉的Response.BinaryWrite是可以正常把檔案下載下來,但原生的Android瀏覽器卻沒有辦法正確下載檔案內容。
其主要原因在於Android內鍵瀏覽器針對Http Header有的處理方式:
(1) 當網頁程式把二進位檔透過Response與HttpHeader中加上(attachment;filename)送給Browser進行下載檔案時,
(2) Android瀏覽器根據接收到指定網址,再一次透過GET的方式同一個網址詢問資料內容,這樣會變成GET到整個網頁的HTML內容;
上面二點是根據網路上搜尋幾個開發論壇討論的歸類,大致上大家都是往Android Browser內鍵針對HTTP Header有特殊處理的部分,
來尋找可以解決的方法。如果用上述二點的說明不太了解的話,可以透過下圖示意它:
從上圖可以清楚了解,Android Browser在接收到要進行attchment任務時,會重新向同一個網址進行GET的Request,
那我們寫在.aspx檔裡面的後端程式,將沒有辦法進行,當然就變成了直接把.aspx檔直接下載下來,而不是下載真正要的檔案。
在了解原因之後,在介紹實作方法之前,先補充針對HTTP Header在Response情形下,透過那些特殊Tag的設定可以讓瀏覽器自動識
別目前Response的結果是一般的HTML、Office檔案(如:.doc, .xls, .ppt, .pdf)、圖片(.jpg/.jpeg, .gif, .png)或壓縮檔案等。
以下分別介紹二個針對檔案下載重要的Tag:
〉Content-Type:
內容類型,這個Tag用於告知瀏覽器收到的內容為何種類型,其語法如:「Content-Type: [type]/[subtype]; parameter」,
其[type]可用的型式,詳細可以參考<MIME headers - 內容類型(Content-Type)>,以下舉常見的Tag,包括:
a. Text:用於標準化地表示的本文信息,用於呈現向XHTML、html或是多種字符集和不同的格式;
b. Application:用於傳輸應用程序數據或者二進制數據;
c. Image:傳輸靜態圖片數據;
其[subtype]的部分,是指定[type]的詳細類型,正是通常會撰寫的部分,其對應表可參考IIS的MIME類型表,
裡面有相當多的檔案類型,如下圖:
透過Response.BinaryWrite(或Response.OutStream)的方式,產生至HttpResponse中讓用戶直接下載下來。
這樣的作法,可以用於常見的檔案,例如:Word/PowerPoint檔、文字檔、圖片等。
然而,這樣的網頁程式在一般網頁上是可以正常運作的,但換到Mobile平台運作時,完全就不是這麼一回事了。
那到底差異在那些地方呢?跟著該篇文章下的標題,很清楚的說明就是在Android的內鍵瀏覽器出現了問題。
根據目前測試下來的結果,Windows Phone(含Windows Mobile)、Opera Mobile/Mini、iPhone與Android(Firefox)是可以正常運作的,
使用過去熟悉的Response.BinaryWrite是可以正常把檔案下載下來,但原生的Android瀏覽器卻沒有辦法正確下載檔案內容。
其主要原因在於Android內鍵瀏覽器針對Http Header有的處理方式:
(1) 當網頁程式把二進位檔透過Response與HttpHeader中加上(attachment;filename)送給Browser進行下載檔案時,
(2) Android瀏覽器根據接收到指定網址,再一次透過GET的方式同一個網址詢問資料內容,這樣會變成GET到整個網頁的HTML內容;
上面二點是根據網路上搜尋幾個開發論壇討論的歸類,大致上大家都是往Android Browser內鍵針對HTTP Header有特殊處理的部分,
來尋找可以解決的方法。如果用上述二點的說明不太了解的話,可以透過下圖示意它:
從上圖可以清楚了解,Android Browser在接收到要進行attchment任務時,會重新向同一個網址進行GET的Request,
那我們寫在.aspx檔裡面的後端程式,將沒有辦法進行,當然就變成了直接把.aspx檔直接下載下來,而不是下載真正要的檔案。
在了解原因之後,在介紹實作方法之前,先補充針對HTTP Header在Response情形下,透過那些特殊Tag的設定可以讓瀏覽器自動識
別目前Response的結果是一般的HTML、Office檔案(如:.doc, .xls, .ppt, .pdf)、圖片(.jpg/.jpeg, .gif, .png)或壓縮檔案等。
以下分別介紹二個針對檔案下載重要的Tag:
〉Content-Type:
內容類型,這個Tag用於告知瀏覽器收到的內容為何種類型,其語法如:「Content-Type: [type]/[subtype]; parameter」,
其[type]可用的型式,詳細可以參考<MIME headers - 內容類型(Content-Type)>,以下舉常見的Tag,包括:
a. Text:用於標準化地表示的本文信息,用於呈現向XHTML、html或是多種字符集和不同的格式;
b. Application:用於傳輸應用程序數據或者二進制數據;
c. Image:傳輸靜態圖片數據;
其[subtype]的部分,是指定[type]的詳細類型,正是通常會撰寫的部分,其對應表可參考IIS的MIME類型表,
裡面有相當多的檔案類型,如下圖: