在 Cordova 剛開始發展時,為了解決下載二進位檔案的問題,建立了 file-transfer 外掛程式。當時,沒有很好的選項可以使用符合標準的 Web API 來解決這個問題。Web 技術歷經曲折才找到解決方案(請參閱 Firefox 的 sendAsBinary
和現已停用的 FileSystem API 的 BlobBuilder 等等),但是現在您可以使用我們的好朋友 XMLHttpRequest 的最新功能,結合一些較新的 JavaScript 類型和物件,來解決這個問題。對於 Cordova 來說,這是一個令人興奮的時刻,因為這個專案的夢想一直是最終減少專案維護的 API 範圍,並看到常規的 Web API 能夠處理這些用例。
因此,Cordova 正在逐步淘汰 file-transfer 外掛程式。「逐步淘汰」是什麼意思?總結來說:
- Cordova 開發社群將不再對 file-transfer 外掛程式進行任何工作。
- 如果您願意,可以繼續使用 file-transfer 外掛程式 - 在可預見的未來,它應該可以正常運作。
- 我們強烈建議 Cordova 使用者轉換為使用符合標準的方式來發送和接收二進位資料。
不過,Apache Cordova 的所有成員都不想讓各位感到無助,所以我們認為最好向您展示如何使用這些較新的 XHR 功能來執行 file-transfer 讓您執行的操作,但它可以在任何現代 Web 瀏覽器中運作!
需求
根據您與底層裝置檔案系統的互動深度,以及在哪些平台上,您可能仍然需要依賴 Cordova File 外掛程式。如果您的應用程式的 JavaScript 中仍然有 requestFileSystem
或 root.fs
的參考,您肯定需要 File 外掛程式,因為這些不是符合標準的 API。請注意並小心!
平台支援
JavaScript 中的二進位類型以及擴展的 XHR 功能,在以下 Cordova 支援的平台上提供,無需任何其他外掛程式:
- Android 4.4 或更新版本。
- iOS 10 或更新版本。
- Windows UWP (8.1、10 或更新版本皆可運作)。
- Windows Phone 8 或更新版本。
一如既往,請查看 caniuse.com 以取得所需的詳細支援,例如 Blob
、Typed Arrays 和 擴展的 XHR 功能。
TL;DR
標準很好,但實際上您必須複製貼上哪些內容才能取代先前的 FileTransfer 範例?我們已經為您準備好了
以下是 FileTransfer 的「將二進位檔案下載到應用程式快取」範例的替代方案
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
console.log('file system open: ' + fs.name);
fs.root.getFile('bot.png', { create: true, exclusive: false }, function (fileEntry) {
console.log('fileEntry is file? ' + fileEntry.isFile.toString());
var oReq = new XMLHttpRequest();
// Make sure you add the domain name to the Content-Security-Policy <meta> element.
oReq.open("GET", "https://cordova.dev.org.tw/static/img/cordova_bot.png", true);
// Define how you want the XHR data to come back
oReq.responseType = "blob";
oReq.onload = function (oEvent) {
var blob = oReq.response; // Note: not oReq.responseText
if (blob) {
// Create a URL based on the blob, and set an <img> tag's src to it.
var url = window.URL.createObjectURL(blob);
document.getElementById('bot-img').src = url;
// Or read the data with a FileReader
var reader = new FileReader();
reader.addEventListener("loadend", function() {
// reader.result contains the contents of blob as text
});
reader.readAsText(blob);
} else console.error('we didnt get an XHR response!');
};
oReq.send(null);
}, function (err) { console.error('error getting file! ' + err); });
}, function (err) { console.error('error getting persistent fs! ' + err); });
以下是 FileTransfer 的「上傳檔案」範例的類似替代方案
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
console.log('file system open: ' + fs.name);
fs.root.getFile('bot.png', { create: true, exclusive: false }, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
// Create a blob based on the FileReader "result", which we asked to be retrieved as an ArrayBuffer
var blob = new Blob([new Uint8Array(this.result)], { type: "image/png" });
var oReq = new XMLHttpRequest();
oReq.open("POST", "http://mysweeturl.com/upload_handler", true);
oReq.onload = function (oEvent) {
// all done!
};
// Pass the blob in to XHR's send method
oReq.send(blob);
};
// Read the file as an ArrayBuffer
reader.readAsArrayBuffer(file);
}, function (err) { console.error('error getting fileentry file!' + err); });
}, function (err) { console.error('error getting file! ' + err); });
}, function (err) { console.error('error getting persistent fs! ' + err); });
請注意,以上兩個範例都依賴 File 外掛程式,因此如果您從應用程式中移除 FileTransfer 外掛程式,請務必新增 File 外掛程式!
長版本
如果您想了解一些啟用二進位資料傳輸的細節,您需要掌握兩個(可能三個)概念。MDN 有一篇關於此主題的精彩文章,值得快速閱讀,但我也會在此提供摘要。
JavaScript 中的二進位類型
長期以來,沒有辦法直接表示二進位資料並在 JavaScript 中存取記憶體中的底層位元組。我們可以將此資料編碼為不同的格式(base64,有人要用嗎?),這很酷,但還是讓我直接處理位元組吧。就我們的目的而言,我們特別關注兩個物件:ArrayBuffer 和 Blob。為什麼我們關心這兩個物件?因為我們可以讓 XHR 以這些類型傳回下載的資料,或將這些類型直接傳遞給 XHR 的 send
方法。
XHR
有兩個較新的 XHR 功能,最初是其開發過程中所謂的「XHR2」的一部分,我們需要利用它們將所有這些功能整合在一起。
對於下載二進位資料,我們需要將 responseType
屬性設定為 arraybuffer
或 blob
- 這會告訴 XHR 我們想要傳回的資料類型。設定了 responseType
後,我們就可以存取唯讀的 response
屬性,以取得代表 XHR 擷取之資料的 ArrayBuffer
或 Blob
物件。
對於上傳二進位資料,則更簡單:將 Blob
或 ArrayBuffer
直接傳遞給 XHR 的 send
方法。就這樣。
摘要
二進位類型和擴展的 XHR 功能在現代桌面瀏覽器和較新的行動瀏覽器(以及 WebViews)中都獲得良好支援。對於現有的 Cordova 使用者,只要您的應用程式以「平台支援」下列出的平台和作業系統版本組合為目標,您就可以順利使用!請記住,如果您依賴某些 File 外掛程式 API(例如 requestFileSystem
、root
或 getFile
),則需要確保將 File 外掛程式新增至您的應用程式。
祝您編碼愉快,符合標準!