Bước 6: Xuất việc cần làm sang hệ thống tệp

Trong bước này, bạn sẽ tìm hiểu:

  • Cách lấy tham chiếu đến một tệp trong hệ thống tệp bên ngoài.
  • Cách ghi vào hệ thống tệp.

Thời gian hoàn thành bước này ước tính là 20 phút.
Để xem trước nội dung bạn sẽ hoàn tất trong bước này, hãy chuyển xuống cuối trang này ↓.

Xuất việc cần làm

Bước này sẽ thêm một nút xuất vào ứng dụng. Khi được nhấp vào, các mục việc cần làm hiện tại sẽ được lưu vào một tệp văn bản do người dùng chọn. Nếu tệp này tồn tại, tệp đó sẽ được thay thế. Nếu không, một tệp mới sẽ được tạo.

Cập nhật quyền

Bạn có thể yêu cầu quyền hệ thống tệp dưới dạng chuỗi để truy cập chỉ có thể đọc hoặc một Đối tượng có các thuộc tính bổ sung. Ví dụ:

// Read only
"permissions": ["fileSystem"]

// Read and write
"permissions": [{"fileSystem": ["write"]}]

// Read, write, autocomplate previous input, and select folder directories instead of files
"permissions": [{"fileSystem": ["write", "retainEntries", "directory"]}]

Bạn cần có quyền đọc và ghi. Trong manifest.json, hãy yêu cầu quyền {fileSystem: [ "write" ] }:

"permissions": [
  "storage", 
  "alarms", 
  "notifications", 
  "webview",
  "<all_urls>", 
  { "fileSystem": ["write"] } 
],

Cập nhật chế độ xem HTML

Trong index.html, hãy thêm nút Export to disk (Xuất sang ổ đĩa) và div để ứng dụng hiển thị thông báo trạng thái:

<footer id="info">
  <button id="toggleAlarm">Activate alarm</button>
  <button id="exportToDisk">Export to disk</button>
  <div id="status"></div>
  ...
</footer>

Ngoài ra, trong index.html, hãy tải tập lệnh export.js:

...
<script src="js/alarms.js"></script>
<script src="js/export.js"></script>

Tạo tập lệnh xuất

Tạo một tệp JavaScript mới có tên export.js bằng mã dưới đây. Lưu tệp này vào thư mục js.

(function() {

  var dbName = 'todos-vanillajs';

  var savedFileEntry, fileDisplayPath;

  function getTodosAsText(callback) {
  }

  function exportToFileEntry(fileEntry) {
  }

  function doExportToDisk() {
  }

  document.getElementById('exportToDisk').addEventListener('click', doExportToDisk);

})();

Hiện tại, export.js chỉ chứa trình nghe lượt nhấp trên nút Export to disk (Xuất sang ổ đĩa) và các đoạn mã giả cho getTodosAsText(), exportToFileEntrydoExportToDisk().

Nhận các mục việc cần làm dưới dạng văn bản

Cập nhật getTodosAsText() để đọc danh sách việc cần làm từ chrome.storage.local và tạo bản trình bày văn bản của các việc cần làm đó:

function getTodosAsText(callback) {
  chrome.storage.local.get(dbName, function(storedData) {
    var text = '';

    if ( storedData[dbName].todos ) {
      storedData[dbName].todos.forEach(function(todo) {
          text += '- ';
          if ( todo.completed ) {
            text += '[DONE] ';
          }
          text += todo.title;
          text += '\n';
        }, '');
    }

    callback(text);

  }.bind(this));
}

Chọn tệp

Cập nhật doExportToDisk() bằng chrome.fileSystem.chooseEntry() để cho phép người dùng chọn một tệp:

function doExportToDisk() {

  if (savedFileEntry) {

    exportToFileEntry(savedFileEntry);

  } else {

    chrome.fileSystem.chooseEntry( {
      type: 'saveFile',
      suggestedName: 'todos.txt',
      accepts: [ { description: 'Text files (*.txt)',
                   extensions: ['txt']} ],
      acceptsAllTypes: true
    }, exportToFileEntry);

  }
}

Tham số đầu tiên của chrome.fileSystem.chooseEntry() là một đối tượng của các tuỳ chọn. Tham số thứ hai là một phương thức gọi lại.

Nếu đã có FileEntry đã lưu, hãy sử dụng FileEntry đó khi gọi exportToFileEntry(). Các tệp tham chiếu tồn tại trong suốt thời gian hoạt động của đối tượng đại diện cho FileEntry. Ví dụ này liên kết FileEntry với cửa sổ ứng dụng để mã JavaScript có thể ghi vào tệp đã chọn mà không cần người dùng tương tác, miễn là cửa sổ ứng dụng vẫn mở.

Sử dụng FileEntry để ghi các mục việc cần làm vào ổ đĩa

Cập nhật exportToFileEntry() để lưu việc cần làm dưới dạng văn bản thông qua API Web FileEntry:

function exportToFileEntry(fileEntry) {
  savedFileEntry = fileEntry;

  var status = document.getElementById('status');

  // Use this to get a file path appropriate for displaying
  chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
    fileDisplayPath = path;
    status.innerText = 'Exporting to '+path;
  });

  getTodosAsText( function(contents) {

    fileEntry.createWriter(function(fileWriter) {

      var truncated = false;
      var blob = new Blob([contents]);

      fileWriter.onwriteend = function(e) {
        if (!truncated) {
          truncated = true;
          // You need to explicitly set the file size to truncate
          // any content that might have been there before
          this.truncate(blob.size);
          return;
        }
        status.innerText = 'Export to '+fileDisplayPath+' completed';
      };

      fileWriter.onerror = function(e) {
        status.innerText = 'Export failed: '+e.toString();
      };

      fileWriter.write(blob);

    });
  });
}

chrome.fileSystem.getDisplayPath() nhận được một đường dẫn tệp có thể hiển thị, xuất ra trạng thái div.

Sử dụng fileEntry.createWriter() để tạo đối tượng FileWriter. Sau đó, fileWriter.write() có thể ghi một Blob vào hệ thống tệp. Sử dụng fileWriter.onwriteend()fileWriter.onerror() để cập nhật trạng thái div.

Để biết thêm thông tin về FileEntry, hãy đọc bài viết Khám phá các API FileSystem trên HTML5Rocks hoặc tham khảo FileEntry docs trên MDN.

Duy trì các đối tượng FileEntry

Nâng cao: Không thể duy trì các đối tượng FileEntry vô thời hạn. Ứng dụng của bạn cần yêu cầu người dùng chọn một tệp mỗi khi khởi chạy ứng dụng. Nếu ứng dụng của bạn buộc phải khởi động lại do sự cố hoặc cập nhật thời gian chạy, thì restoreEntry() là một tuỳ chọn để khôi phục FileEntry.

Nếu muốn, hãy thử nghiệm bằng cách lưu mã nhận dạng do retainEntry() trả về và khôi phục mã nhận dạng đó khi khởi động lại ứng dụng. (Gợi ý: Thêm trình nghe vào sự kiện onRestarted trong trang ở chế độ nền.)

Chạy ứng dụng Todo đã hoàn thiện

Bạn đã hoàn tất Bước 6! Tải lại ứng dụng và thêm một số việc cần làm. Nhấp vào Xuất sang ổ đĩa để xuất danh sách việc cần làm sang tệp .txt.

Ứng dụng Todo với các việc cần làm đã xuất

Thông tin khác

Để biết thêm thông tin chi tiết về một số API được giới thiệu trong bước này, hãy tham khảo:

Bạn đã sẵn sàng chuyển sang bước tiếp theo chưa? Chuyển đến Bước 7 – Phát hành ứng dụng »