Etapa 6: exportar tudo para o sistema de arquivos

Nesta etapa, você vai aprender:

  • Como conseguir uma referência a um arquivo no sistema de arquivos externo.
  • Como gravar no sistema de arquivos.

Tempo estimado para concluir esta etapa: 20 minutos.
Para conferir uma prévia do que você vai concluir nesta etapa, role até a parte de baixo da página ↓.

Exportar tudo

Esta etapa adiciona um botão de exportação ao app. Quando clicado, os itens de tarefas atuais são salvos em um arquivo de texto selecionado pelo usuário. Se o arquivo existir, ele será substituído. Caso contrário, um novo arquivo será criado.

Atualizar permissões

As permissões do sistema de arquivos podem ser solicitadas como uma string para acesso somente leitura ou um objeto com propriedades adicionais. Exemplo:

// 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"]}]

Você precisa de acesso de leitura e gravação. Em manifest.json, solicite a permissão {fileSystem: [ "write" ] }:

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

Atualizar a visualização em HTML

Em index.html, adicione um botão Exportar para disco e um div em que o app mostra uma mensagem de status:

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

Ainda em index.html, carregue o script export.js:

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

Criar script de exportação

Crie um novo arquivo JavaScript chamado export.js usando o código abaixo. Salve-o na pasta js.

(function() {

  var dbName = 'todos-vanillajs';

  var savedFileEntry, fileDisplayPath;

  function getTodosAsText(callback) {
  }

  function exportToFileEntry(fileEntry) {
  }

  function doExportToDisk() {
  }

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

})();

No momento, o export.js contém apenas um listener de clique no botão Exportar para disco e stubs para getTodosAsText(), exportToFileEntry e doExportToDisk().

Receber itens de tarefas como texto

Atualize getTodosAsText() para que ele leia todos os itens de chrome.storage.local e gere uma representação textual deles:

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));
}

Escolha um arquivo

Atualize doExportToDisk() com chrome.fileSystem.chooseEntry() para permitir que o usuário escolha um arquivo:

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);

  }
}

O primeiro parâmetro de chrome.fileSystem.chooseEntry() é um objeto de opções. O segundo parâmetro é um método de callback.

Se já houver um FileEntry salvo, use-o ao chamar exportToFileEntry(). As referências de arquivo existem durante o ciclo de vida do objeto que representa o FileEntry. Esse exemplo vincula FileEntry à janela do app para que o código JavaScript possa gravar no arquivo selecionado sem nenhuma interação do usuário, desde que a janela do app permaneça aberta.

Use FileEntry para gravar todos os itens no disco

Atualize exportToFileEntry() para salvar todos como texto usando a API da 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() recebe um caminho de arquivo que pode ser exibido e que gera o status div.

Use fileEntry.createWriter() para criar um objeto FileWriter. O fileWriter.write() pode gravar um Blob no sistema de arquivos. Use fileWriter.onwriteend() e fileWriter.onerror() para atualizar o status div.

Para mais informações sobre FileEntry, leia Como usar as APIs FileSystem no HTML5Rocks ou consulte FileEntry docs no MDN.

Persistir objetos FileEntry

Avançado: os objetos FileEntry não podem ser mantidos indefinidamente. O app precisa pedir ao usuário para escolher um arquivo sempre que for iniciado. Se o app foi forçado a reiniciar devido a uma falha ou atualização do ambiente de execução, restoreEntry() é uma opção para restaurar um FileEntry.

Se quiser, teste salvando o ID retornado por retainEntry() e restaurando-o na reinicialização do app. Dica: adicione um listener ao evento onRestarted na página em segundo plano.

Iniciar o app de tarefas concluído

Você concluiu a etapa 6. Atualize o app e adicione alguns itens. Clique em Exportar para disco para exportar todos os todos para um arquivo .txt.

O app de tarefas com tarefas exportadas

Para saber mais

Para informações mais detalhadas sobre algumas das APIs apresentadas nesta etapa, consulte:

Tudo pronto para continuar para a próxima etapa? Acesse a Etapa 7: publicar o app »