Paso 6: Exporta todos al sistema de archivos

En este paso, aprenderás lo siguiente:

  • Cómo obtener una referencia a un archivo en el sistema de archivos externo
  • Cómo escribir en el sistema de archivos

Tiempo estimado para completar este paso: 20 minutos
Para obtener una vista previa de lo que completarás en este paso, ve a la parte inferior de esta página ↓.

Exportar tareas pendientes

En este paso, se agregará un botón de exportación a la app. Cuando se hace clic en él, las tareas pendientes actuales se guardan en un texto que seleccionó el usuario. Si el archivo existe, se reemplaza. De lo contrario, se creará un archivo nuevo.

Actualizar permisos

Los permisos del sistema de archivos pueden solicitarse como una cadena para acceso de solo lectura, o como un objeto con propiedades adicionales. Por ejemplo:

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

Necesitas acceso de lectura y escritura. En manifest.json, solicita {fileSystem: [ "write" ] }. permiso:

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

Actualizar vista HTML

En index.html, agrega un botón Exportar al disco y un div donde la app muestre un mensaje de estado:

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

También en index.html, carga la secuencia de comandos export.js:

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

Crear secuencia de comandos de exportación

Crea un nuevo archivo JavaScript llamado export.js con el siguiente código. Guárdalo en la carpeta js.

(function() {

  var dbName = 'todos-vanillajs';

  var savedFileEntry, fileDisplayPath;

  function getTodosAsText(callback) {
  }

  function exportToFileEntry(fileEntry) {
  }

  function doExportToDisk() {
  }

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

})();

En este momento, export.js solo contiene un objeto de escucha de clics en el botón Exportar al disco y stubs para getTodosAsText(), exportToFileEntry y doExportToDisk().

Obtener elementos de tareas pendientes como texto

Actualiza getTodosAsText() para que lea todos los de chrome.storage.local y genere un informe una representación visual de ellos:

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

Elige un archivo

Actualiza doExportToDisk() con chrome.fileSystem.chooseEntry() para permitir que el usuario elija un archivo:

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

  }
}

El primer parámetro de chrome.fileSystem.chooseEntry() es un objeto de opciones. El segundo es un método de devolución de llamada.

Si ya hay un FileEntry guardado, úsalo cuando llames a exportToFileEntry(). Archivo existen durante la vida útil del objeto que representa el FileEntry. Este ejemplo vincula FileEntry en la ventana de la app para que el código JavaScript pueda escribir en el archivo seleccionado sin ningún usuario interacción mientras la ventana de la app permanezca abierta.

Usa FileEntry para escribir elementos de todos en el disco

Actualiza exportToFileEntry() para guardar los todos como texto a través de la API web de 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() obtiene una ruta de archivo visible que da como resultado el estado. div

Usa fileEntry.createWriter() para crear un objeto FileWriter. Luego, fileWriter.write() podrá escribir un BLOB al sistema de archivos. Usa fileWriter.onwriteend() y fileWriter.onerror() para la actualización el estado div.

Para obtener más información acerca de FileEntry, lee Explora las APIs del sistema de archivos en HTML5Rocks. consulta FileEntry docs en MDN.

Conserva objetos FileEntry

Avanzado: Los objetos FileEntry no se pueden conservar de forma indefinida. Tu app debe solicitarle al usuario elegir un archivo cada vez que se inicie la aplicación. Si tu app se vio forzada a reiniciarse debido a un tiempo de ejecución falla o actualización, restoreEntry() es una opción para restablecer una FileEntry.

Si lo deseas, puedes experimentar guardando el ID que muestra retainEntry() y restableciéndolo en la app. reiniciar. (Sugerencia: Agrega un objeto de escucha al evento onRestarted en la página en segundo plano).

Inicia tu app de tareas pendientes terminada

Has completado el paso 6. Vuelve a cargar tu app y agrega algunas tareas pendientes. Haz clic en Exportar al disco para exportar tu todos a un archivo .txt.

La app de tareas pendientes con todos los elementos exportados

Más información

Para obtener información más detallada sobre algunas de las APIs presentadas en este paso, consulta:

¿Todo listo para continuar con el siguiente paso? Ve al Paso 7: Publica tu app »