API lưu trữ

Hầu hết mọi khía cạnh của quá trình phát triển ứng dụng đều liên quan đến một số yếu tố gửi hoặc nhận dữ liệu. Bắt đầu từ những kiến thức cơ bản, bạn nên sử dụng khung MVC để thiết kế và triển khai ứng dụng sao cho dữ liệu hoàn toàn tách biệt với chế độ xem của ứng dụng trên dữ liệu đó (xem phần Cấu trúc video nhạc).

Bạn cũng cần suy nghĩ về cách xử lý dữ liệu khi ứng dụng không có kết nối mạng (xem phần Ngoại tuyến trước tiên). Tài liệu này giới thiệu ngắn gọn các tuỳ chọn lưu trữ để gửi, nhận và lưu dữ liệu trên máy; phần còn lại của tài liệu này sẽ hướng dẫn bạn cách sử dụng các API Hệ thống tệp và Đồng bộ hoá tệp hệ thống của Chrome (xem thêm fileSystem APIsyncFileSystem API).

Gói bộ nhớ

Các ứng dụng đóng gói dùng nhiều cơ chế để gửi và nhận dữ liệu. Đối với dữ liệu bên ngoài (tài nguyên, trang web), bạn cần nắm rõ Chính sách bảo mật nội dung (CSP). Tương tự như Tiện ích của Chrome, bạn có thể sử dụng XMLHttpRequests trên nhiều nguồn gốc để giao tiếp với các máy chủ từ xa. Bạn cũng có thể tách riêng các trang bên ngoài để đảm bảo an toàn cho phần còn lại của ứng dụng (xem nội dung Nhúng trang web bên ngoài).

Khi lưu dữ liệu trên máy, bạn có thể sử dụng API Bộ nhớ Chrome để lưu một lượng nhỏ dữ liệu chuỗi và IndexedDB để lưu dữ liệu có cấu trúc. Với IndexedDB, bạn có thể lưu trữ các đối tượng JavaScript vào một kho lưu trữ đối tượng và sử dụng các chỉ mục của cửa hàng đó để truy vấn dữ liệu (để tìm hiểu thêm, hãy xem Hướng dẫn về danh sách việc cần làm đơn giản của HTML5 Rock). Đối với tất cả các loại dữ liệu khác, chẳng hạn như dữ liệu nhị phân, hãy dùng các Filesystem và Sync Filesystem API (API Hệ thống tệp đồng bộ hoá) và Đồng bộ hoá.

API hệ thống tệp và đồng bộ hóa hệ thống tệp của Chrome mở rộng API hệ thống tệp HTML5. Với API hệ thống tệp của Chrome, ứng dụng có thể tạo, đọc, điều hướng và ghi vào một mục có hộp cát trong hệ thống tệp trên máy của người dùng. Ví dụ: Ứng dụng chia sẻ ảnh có thể sử dụng API Hệ thống tệp để đọc và ghi bất kỳ ảnh nào mà người dùng chọn.

Với API Hệ thống tệp đồng bộ hoá của Chrome, các ứng dụng có thể lưu và đồng bộ hoá dữ liệu trên Google Drive của người dùng để có thể sử dụng cùng một dữ liệu trên các ứng dụng khác nhau. Ví dụ: ứng dụng trình chỉnh sửa văn bản dựa trên đám mây có thể tự động đồng bộ hoá các tệp văn bản mới với tài khoản Google Drive của người dùng. Khi người dùng mở trình chỉnh sửa văn bản trong một ứng dụng mới, Google Drive sẽ đẩy các tệp văn bản mới vào bản sao đó của trình chỉnh sửa văn bản đó.

Sử dụng API Hệ thống tệp Chrome

Đang thêm quyền hệ thống tệp

Để sử dụng API Hệ thống tệp của Chrome, bạn cần thêm quyền "fileSystem" vào tệp kê khai để có thể được người dùng cho phép lưu trữ dữ liệu cố định.

"permissions": [
  "...",
  "fileSystem"
]

Các tuỳ chọn cho người dùng để chọn tệp

Người dùng muốn chọn tệp theo cách họ thường làm. Ít nhất, họ cần có một nút "chọn tệp" và trình chọn tệp tiêu chuẩn. Nếu ứng dụng của bạn sử dụng nhiều hoạt động giao tệp, bạn cũng nên triển khai tính năng kéo và thả (xem bên dưới, cũng như xem Kéo và thả HTML5 gốc).

Lấy đường dẫn của một fileEntry

Để lấy đường dẫn đầy đủ của tệp mà người dùng đã chọn, fileEntry, hãy gọi getDisplayPath():

function displayPath(fileEntry) {
  chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
    console.log(path)
  });
}

Triển khai thao tác kéo và thả

Nếu bạn cần triển khai lựa chọn kéo và thả, bạn nên bắt đầu bằng trình điều khiển tệp kéo và thả (dnd.js) trong mẫu filesystem-access. Bộ điều khiển tạo một mục nhập tệp từ DataTransferItem thông qua thao tác kéo và thả. Trong ví dụ này, fileEntry được đặt thành mục thả xuống đầu tiên.

var dnd = new DnDFileController('body', function(data) {
  var fileEntry = data.items[0].webkitGetAsEntry();
  displayPath(fileEntry);
});

Đọc tệp

Mã sau đây sẽ mở tệp (chỉ có thể đọc) và đọc tệp dưới dạng văn bản bằng cách sử dụng đối tượng FileReader. Nếu tệp không tồn tại, hệ thống sẽ gửi lỗi.

var chosenFileEntry = null;

chooseFileButton.addEventListener('click', function(e) {
  chrome.fileSystem.chooseEntry({type: 'openFile'}, function(readOnlyEntry) {

    readOnlyEntry.file(function(file) {
      var reader = new FileReader();

      reader.onerror = errorHandler;
      reader.onloadend = function(e) {
        console.log(e.target.result);
      };

      reader.readAsText(file);
    });
    });
});

Ghi tệp

Hai trường hợp sử dụng phổ biến để viết tệp là "Save" (Lưu) và "Save as" (Lưu dưới dạng). Mã sau đây tạo một writableEntry từ chosenFileEntry chỉ có thể đọc và ghi tệp đã chọn vào đó.

 chrome.fileSystem.getWritableEntry(chosenFileEntry, function(writableFileEntry) {
    writableFileEntry.createWriter(function(writer) {
      writer.onerror = errorHandler;
      writer.onwriteend = callback;

    chosenFileEntry.file(function(file) {
      writer.write(file);
    });
  }, errorHandler);
});

Mã sau đây sẽ tạo một tệp mới có chức năng "Lưu dưới dạng" và ghi blob mới vào tệp đó bằng phương thức writer.write().

chrome.fileSystem.chooseEntry({type: 'saveFile'}, function(writableFileEntry) {
    writableFileEntry.createWriter(function(writer) {
      writer.onerror = errorHandler;
      writer.onwriteend = function(e) {
        console.log('write complete');
      };
      writer.write(new Blob(['1234567890'], {type: 'text/plain'}));
    }, errorHandler);
});

Sử dụng API Hệ thống tệp Chrome Sync

Khi sử dụng bộ nhớ tệp có thể đồng bộ hoá, các đối tượng dữ liệu được trả về có thể được vận hành theo cách tương tự như các hệ thống tệp ngoại tuyến cục bộ trong FileSystem API, nhưng cần thực hiện thêm việc đồng bộ hoá (và tự động) dữ liệu đó với Google Drive.

Thêm quyền hệ thống tệp đồng bộ hoá

Để sử dụng API Hệ thống tệp đồng bộ hoá của Chrome, bạn cần thêm quyền "syncFileSystem" vào tệp kê khai để có thể được người dùng cấp quyền lưu trữ và đồng bộ hoá dữ liệu cố định.

"permissions": [
  "...",
  "syncFileSystem"
]

Đang khởi tạo bộ nhớ tệp có thể đồng bộ hoá

Để kích hoạt bộ nhớ tệp có thể đồng bộ hoá trong ứng dụng, bạn chỉ cần gọi syncFileSystem.requestFileSystem. Phương thức này trả về một hệ thống tệp có thể đồng bộ hoá được Google Drive hỗ trợ, ví dụ:

chrome.syncFileSystem.requestFileSystem(function (fs) {
   // FileSystem API should just work on the returned 'fs'.
   fs.root.getFile('test.txt', {create:true}, getEntryCallback, errorCallback);
});

Giới thiệu về trạng thái đồng bộ hoá tệp

Sử dụng syncFileSystem.getFileStatus để biết trạng thái đồng bộ hoá của một tệp hiện tại:

chrome.syncFileSystem.getFileStatus(entry, function(status) {...});

Các giá trị trạng thái đồng bộ hoá tệp có thể là một trong những giá trị sau: 'synced', 'pending' hoặc 'conflicting'. "Đã đồng bộ hoá" có nghĩa là tệp được đồng bộ hoá hoàn toàn; không có thay đổi cục bộ nào đang chờ xử lý chưa được đồng bộ hoá với Google Drive. Tuy nhiên, có thể có những thay đổi đang chờ xử lý ở phía Google Drive mà chưa được tìm nạp.

Trạng thái "Đang chờ xử lý" có nghĩa là tệp có các thay đổi đang chờ xử lý chưa được đồng bộ hoá với Google Drive. Nếu ứng dụng đang chạy trực tuyến, các thay đổi cục bộ (gần như) sẽ được đồng bộ hoá ngay lập tức với Google Drive, và sự kiện syncFileSystem.onFileStatusChanged sẽ được kích hoạt với trạng thái 'synced' (xem để biết thêm thông tin chi tiết ở bên dưới).

Hệ thống sẽ kích hoạt syncFileSystem.onFileStatusChanged khi trạng thái của tệp thay đổi thành 'conflicting'. "Xung đột" nghĩa là có các thay đổi xung đột trên cả bộ nhớ cục bộ và Google Drive. Tệp chỉ có thể ở trạng thái này nếu bạn đặt chính sách giải quyết xung đột thành 'manual'. Chính sách mặc định là 'last_write_win' và các xung đột được tự động giải quyết bằng chính sách đơn giản theo dõi bên được ghi cuối cùng. Bạn có thể thay đổi chính sách giải quyết xung đột của hệ thống bằng syncFileSystem.setConflictResolutionPolicy.

Nếu bạn đặt chính sách giải quyết xung đột thành 'manual' và một tệp dẫn đến trạng thái 'conflicting', thì ứng dụng vẫn có thể đọc và ghi tệp đó dưới dạng tệp ngoại tuyến cục bộ, nhưng các thay đổi sẽ không được đồng bộ hoá và tệp sẽ được tách khỏi các thay đổi từ xa được thực hiện trên các ứng dụng khác cho đến khi xung đột được giải quyết. Cách dễ nhất để giải quyết xung đột là xoá hoặc đổi tên phiên bản tệp cục bộ. Điều này buộc phiên bản từ xa phải được đồng bộ hoá, trạng thái xung đột được giải quyết và sự kiện onFileStatusChanged được kích hoạt với trạng thái 'synced'.

Nghe các thay đổi về trạng thái đã đồng bộ hoá

Sự kiện syncFileSystem.onFileStatusChanged được kích hoạt khi trạng thái đồng bộ hóa của tệp thay đổi. Ví dụ: giả sử một tệp có các thay đổi đang chờ xử lý và đang ở trạng thái "đang chờ xử lý". Ứng dụng có thể đã ở trạng thái ngoại tuyến để thay đổi sắp được đồng bộ hoá. Khi dịch vụ đồng bộ hoá phát hiện thay đổi cục bộ đang chờ xử lý và tải thay đổi đó lên Google Drive, dịch vụ này sẽ kích hoạt sự kiện onFileStatusChanged với các giá trị sau: { fileEntry:a fileEntry for the file, status: 'synced', action: 'updated', direction: 'local_to_remote' }.

Tương tự, bất kể các hoạt động cục bộ là gì, dịch vụ đồng bộ hoá có thể phát hiện các thay đổi từ xa do một ứng dụng khác thực hiện và tải các thay đổi đó từ Google Drive xuống bộ nhớ cục bộ. Nếu thay đổi từ xa là để thêm tệp mới, thì một sự kiện có các giá trị sau sẽ được kích hoạt: { fileEntry: a fileEntry for the file, status: 'synced', action: 'added', direction: 'remote_to_local' }.

Nếu cả phía cục bộ và phía từ xa đều có các thay đổi gây xung đột cho cùng một tệp và nếu chính sách giải quyết xung đột được đặt thành 'manual', thì trạng thái tệp sẽ thay đổi thành trạng thái conflicting, được tách khỏi dịch vụ đồng bộ hoá và sẽ không được đồng bộ hoá cho đến khi xung đột được giải quyết. Trong trường hợp này, một sự kiện có các giá trị sau sẽ được kích hoạt: { fileEntry: a fileEntry for the file, status: 'conflicting', action: null, direction: null }.

Bạn có thể thêm trình nghe cho sự kiện này để phản hồi mọi thay đổi về trạng thái. Ví dụ: ứng dụng Trình phát nhạc Chrome theo dõi mọi bản nhạc mới được đồng bộ hoá từ Google Drive, nhưng chưa được nhập vào bộ nhớ cục bộ của người dùng trên một ứng dụng cụ thể. Mọi bản nhạc tìm thấy sẽ được đồng bộ hoá với ứng dụng đó:

chrome.syncFileSystem.onFileStatusChanged.addListener(function(fileInfo) {
  if (fileInfo.status === 'synced') {
    if (fileInfo.direction === 'remote_to_local') {
      if (fileInfo.action === 'added') {
        db.add(fileInfo.fileEntry);
      } else if (fileInfo.action === 'deleted') {
        db.remove(fileInfo.fileEntry);
      }
    }
  }
});

Kiểm tra mức sử dụng API

Để kiểm tra lượng dữ liệu mà API đang sử dụng, hãy truy vấn thư mục hộp cát cục bộ của ứng dụng hoặc các byte sử dụng do syncFileSystem.getUsageAndQuota:

chrome.syncFileSystem.getUsageAndQuota(fileSystem, function (storageInfo) {
   updateUsageInfo(storageInfo.usageBytes);
   updateQuotaInfo(storageInfo.quotaBytes);
});

Bạn cũng có thể xem bộ nhớ của dịch vụ phụ trợ đồng bộ hoá của người dùng (trong Google Drive). Các tệp đã đồng bộ hoá được lưu trong một thư mục Google Drive ẩn, Hệ thống tệp có thể đồng bộ hoá Chrome. Thư mục này sẽ không hiển thị trong danh sách "Drive của tôi" nhưng có thể truy cập được bằng cách tìm kiếm tên thư mục trong hộp tìm kiếm. (Lưu ý rằng bố cục của thư mục từ xa không được đảm bảo sẽ duy trì khả năng tương thích ngược giữa các bản phát hành.)