angular2/angular4 如何通過$http的post方法請求下載二進(jìn)制的Excel文件

下面給大家介紹一下我遇到的一個坑,如果你也遇到了,那恭喜你,你一定能找到答案:angular2/angular4 如何通過$http的post方法請求下載二進(jìn)制的Excel文件? (angular1自行百度)

問題描述:

后臺返回的是一個二進(jìn)制的Excel流,請求頭如下:

Access-Control-Allow-Origin:*

Cache-Control:private

Content-Disposition:attachment;filename=%E9%A9%BE%E9%A9%B6%E5%91%98%E8%AF%84%E5%88%86.xlsx

Content-Type:application/vnd.ms-excel; charset=UTF-8

Date:Thu, 15 Jun 2017 03:19:11 GMT

Server:Microsoft-IIS/8.5

Transfer-Encoding:chunked

X-AspNet-Version:4.0.30319

X-Powered-By:ASP.NET

給的請求方式是post,然后帶一堆的參數(shù),現(xiàn)在求如何請求?

當(dāng)時覺得后臺應(yīng)該是返回的是一個Excel文件下載的地址,于是按照正常的請求發(fā)起請求,結(jié)果是然并卵,報錯了,返回數(shù)據(jù)如下:



返回結(jié)果是一個二進(jìn)制流,還會有一個請求失敗的提示

排除后端問題,那前端應(yīng)該怎么請求呢?

當(dāng)時想到的第一種方式是修改響應(yīng)頭:

Content-Type:application/vnd.ms-excel; charset=UTF-8

原來的響應(yīng)頭是Content-Type: application/json,改成xsl對應(yīng)的二進(jìn)制響應(yīng)頭應(yīng)該就沒錯了吧,結(jié)果依然是然并卵,直接給我報500錯誤

于是乎,決定谷歌之,百度之,發(fā)現(xiàn)處理這種辦法的大多數(shù)是這樣的:

$http({

url: 'your/webservice',

method: "POST",

data: json, //this is your json data string

headers: {

'Content-type': 'application/json'

},

responseType: 'arraybuffer'

}).success(function (data, status, headers, config) {

var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});

var objectUrl = URL.createObjectURL(blob);

window.open(objectUrl);

}).error(function (data, status, headers, config) {

//upload failed

});

基本上大部分方法跟上面的大同小異,于是按著這個方法試了試,其中的重點(diǎn)配置是 responseType: 'arraybuffer', 因?yàn)閍ngular的http模塊里面有對responseType有定義:

responseType: ResponseContentType | null;

找到ResponseContentType:

export declare enum ResponseContentType {

Text = 0,

Json = 1,

ArrayBuffer = 2,

Blob = 3,

}

原來它還有這幾個參數(shù),那ArrayBuffer 對應(yīng)就是responseType: 2, 依然是沒有用,結(jié)果跟直接用post請求一樣

如果你也經(jīng)歷了這些,往下看吧!

這是我在想,ResponseContentType 里面的其他的屬性都是干嘛的, 前面2個很好理解,一個是文本格式的, 一個是json格式的,那ArrayBuffer和Blob是什么意思呢?我只是簡單的將一下,想深入了解,可以看看張鑫旭的 理解DOMString、Document、FormData、Blob、File、ArrayBuffer數(shù)據(jù)類型

ArrayBuffer表示二進(jìn)制數(shù)據(jù)的原始緩沖區(qū),該緩沖區(qū)用于存儲各種類型化數(shù)組的數(shù)據(jù),ArrayBuffer是二進(jìn)制數(shù)據(jù)通用的固定長度容器。

Blob表示二進(jìn)制大對象,專門存放二進(jìn)制數(shù)據(jù)。

額,聽不懂?可以這么理解,ArrayBuffer就是作為數(shù)據(jù)源提前寫入在內(nèi)存中,就是提前釘死在某個區(qū)域,長度也固定,萬年不變,Blob是個更高一級的大分類,包含ArrayBuffer,還有更多;

還有一種理解就是XMLHttpRequest 第二版允許服務(wù)器返回二進(jìn)制數(shù)據(jù),這時分成兩種情況。如果明確知道返回的二進(jìn)制數(shù)據(jù)類型,可以把返回類型(responseType)設(shè)為arraybuffer;如果不知道,就設(shè)為blob。

反正不管怎么樣吧,試一試blob,于是就有我最終的代碼:

download(url?:string, form?:any){

this.downloadHeader;

return this.http.post(url, form, this.options).map(res => res.json).catch(this.handleError);

}

downloadHeader{

if (localStorage.getItem(environment.local_storage_account)) {

this.headers = new Headers({'token': JSON.parse(localStorage.getItem(environment.local_storage_account)).Token });

this.options = new RequestOptions({ headers: this.headers, responseType: 3 });

}

}

每個人的代碼寫法不一樣,請忽略其他的,只關(guān)注responseType: 3

最后返回的response是:

Blob {size: 4384, type: "application/vnd.ms-excel"}

那就可以用大家常用的blob方法來下載了:

var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});

var objectUrl = URL.createObjectURL(blob);

window.open(objectUrl);

這里有一個問題,就是很多瀏覽器可能會墻掉彈窗,導(dǎo)致你的文件沒法正常下載,所以我們用a標(biāo)簽的形式來下載,思路就是成功后新建一個帶下載地址的a標(biāo)簽,然后被動觸發(fā)點(diǎn)擊:

var blob = new Blob([res], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});

var objectUrl = URL.createObjectURL(blob);

var a = document.createElement('a');

document.body.appendChild(a);

a.setAttribute('style', 'display:none');

a.setAttribute('href', objectUrl);

a.setAttribute('download', fileName);

a.click;

URL.revokeObjectURL(objectUrl);

結(jié)束后釋放url,好了,大概的思路就是這樣了,如果你還有什么不明白的,歡迎給我留言,我會盡快給你回復(fù)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容