PhoneGap:檔案同步

在前面兩篇 檔案存取(一) 以及 檔案存取(二) 已經說明如何將使用者資訊儲存至檔案(純文字文件)中。不過這些檔案若只是存在本機端,也沒有什麼義意,必須使用檔案同步(FileTransfer)將檔案上傳至伺服器。相較於 FileSystem,FileTransfer 簡單很多,不過必須額外撰寫 Server 端的程式(本篇使用PHP)。詳細的說明內容可以參考官方網站

載入 API

FileTransfer 和 FileSystem 一樣,必須在 deviceready 事件觸發之後才能作用(參考檔案存取(一))。另外也別忘了在 HTML 網頁裡載入 cordova.js (參考PhoneGap建置)。

<gap:plugin name="org.apache.cordova.device" />
    <gap:plugin name="org.apache.cordova.file" />
    <gap:plugin name="org.apache.cordova.file-transfer" />

上傳檔案

上傳檔案的呼叫,一般來說會配合按鈕,或是 FileSystem 的檔案列表,不會直接在 deviceready 後執行。不過為了提醒讀者要確保 deviceready 已經呼叫,所以下面的程式碼把 uploadFile() 寫在 onDeviceReady() 中。

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
    //在deviceready之後才能進行同步
    //uploadFile(filepath);     //filepath為上傳檔案的路徑
}
function uploadFile(filepath) {
    var options = new FileUploadOptions();
    options.fileName = "newFileName.txt";   //儲存至Server端的檔案名稱
    options.mimeType = "text/plain";    //預設值為image/jpeg

    var params = {};    //設定上傳參數
    params.key = "value";   //設定參數key與value
    options.params = params;

    var ft = new FileTransfer();
    ft.upload(filepath, encodeURI("http://www.moke.tw/saveFile.php"),
        function(r) {   //上傳成功
            console.log("Code = " + r.responseCode);
            console.log("Response = " + r.response);
        }, function(error) {    //上傳失敗
            alert("An error has occurred: Code = " + error.code);
    }, options);
}

上面第 16 行的 saveFile.php 並不存在,必須自行撰寫放在 Server 端(這裡只是表示 Server 的網址)。接收檔案的程式不一定要用 PHP,選擇自己方便的即可。下面是 PHP 接收檔案的參考語法,第 1 行的 $path 是上傳目錄,預設為根目錄。

$path = "";
if( $_FILES["file"] != null ) {
    if( $_FILES["file"]["error"] > 0 ) {
        echo "上傳錯誤。Error code: " . $_FILES["file"]["error"];
    }
    else {
        if(!is_dir($path)) mkdir($path, 0755, true);    //如果目錄不存在,建立目錄
        move_uploaded_file($_FILES["file"]["tmp_name"], $path . $_FILES["file"]["name"]);
        echo "done";    //輸出成功上傳的識別字串
    }
}

下載檔案

下載檔案是把檔案從 Server 端下載,儲存至 Client 端。它的重點只有二個,Server 端檔案位置,以及 Client 端想要儲存到那裡。參考下面的程式碼,第 1 至 15 行完全就是檔案存取(一)的內容,它的目的只是為了讓第 1 行的 filesystem 物件有內容,可以讀取 Client 端的檔案位置。第 16 行開始才是 FileTransfer 下載檔案的主要程式碼。取得 Server 端的檔案路徑與檔名後,透過 filesystem.root.toURL() 取得 Client 端的存取路徑,剩下的就是下載成功與失敗的處理。

var filesystem = null;

document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {
    window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;

    if (window.requestFileSystem) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 1024 * 1024 * 5 , function(fs) {
            filesystem = fs;
        }, errorHandler);
    } else {
        alert("Sorry! Your browser doesn\'t support the FileSystem API :(");
    }
}
function fileDownload(fileURL) {    //fileURL為Server端的檔案路徑
    var fileName = fileURL.substr(fileURL.lastIndexOf('/')+1);  //取得檔名

    var ft = new FileTransfer();
    ft.download(encodeURI(fileURL), filesystem.root.toURL() + fileName,
        function(entry) {   //下載成功
            console.log("download complete: " + entry.toURL());
        }, function(error) {    //下載失敗
            console.log("upload error code" + error.code);
    });
}

Client 端的儲存路徑類似 cdvfile://localhost/persistent/path/to/downloads/,由於不同機種的儲存路徑不太一樣,所以建議還是用 filesystem 讀取APP的根目錄再做儲存比較好。