前幾天做builder項目有個pdf下載需求,然後把在做這個的問題和方法記錄下來(僅供參考)。
1.概念
有些同學很有可能會疑問,pdf下載和預覽功能,什麼時候是下載?什麼時候是預覽?
其實這個和幾方面的因素有關係,假如一個a標籤,herf指向個路徑 ,如下圖:
那麼默認情況打開是預覽的(如果瀏覽器有插件是直接預覽的):
那麼如果服務端做了對文件配置(我到網站隨便copy的一段,nginx服務端配置pdf文件下載):
那麼所有做過濾的文件都會變成下載狀態!
如果你去往服務器發送請求,通過接口去請求pdf文件的話,那麼接口的response通過響應頭也可以控制。
下載 (attachment):
inline(預覽):
如果一個文件又需要下載,又需要預覽怎麼辦?
同一個服務器上是做不到的,除非在不用的服務器上。
1.實現
有了上面的概念再來說說怎麼實現的,之前一直以爲如果後端接口返回一個文件流給我,前端這邊只要請求成功的話是可以直接下載的,結果偏偏不是,接口返回來的是一段亂碼(二進制的),不知道是啥玩意,看下圖:
如果碰到這種情況,你在請求頭裏面一定要配置responseType: “blob”,因爲只有它才能解析二進制的文件:
RESTfulService.prototype.templatedownload = function (parameters) {
var that = this;
var url = that.CGP_REST + that.API + 'materialViewTypePrecessConfigController/template/download';
return this.$http({
method: "GET",
url: url,
params: parameters,
responseType: "blob"
})
};
之前用的是$resource,不知道什麼問題(配了responseType: "blob"也解析不了),因爲項目用的是angular,所以後來改成了 angular的 $http(如果知道原因的話,可以分享下!)
然後拿到response結果後,要創建blob對象去解析這個二進制文件流:
var blob = new Blob([response.data], {
type: response.data.type
});
var pdf = document.createElement('a');
pdf.href = window.URL.createObjectURL(blob);
pdf.download = 'template.pdf';
document.body.appendChild(pdf);
pdf.click();
pdf.remove();
window.URL.revokeObjectURL(pdf.href);
或者還有一種另外的方法,參數就是請求的接口地址(直接簡單粗暴):
window.open('http://192.168.41.161:8080/api/materialViewTypePrecessConfigController/template/download?sbomPath=1947217&ssmvtId=2025302&propertyModelId=2036805&access_token=b4c6102f-2c7f-45c3-ad5d-001f7b707300')
這種簡單粗暴的方式缺陷就是抓不到請求的之後成功或者失敗的狀態!如果請求失敗了需要再次retry的話這個你就不知道它的狀態了!不好控制!方法有很多種,可以自己去嘗試!好了說到這裏都已經說的差不多了,有不正的地方請指正,不勝感激!!歡樂的時光總是過得特別快,又到時候和大家講拜拜!!