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, desplázate hasta la parte inferior de esta página ↓.
Exportar todos
En este paso, se agrega un botón de exportación a la app. Cuando se hace clic en él, los elementos de la lista de tareas pendientes actuales se guardan en un archivo de texto que selecciona el usuario. Si el archivo ya existe, se reemplazará. De lo contrario, se creará un archivo nuevo.
Actualizar permisos
Los permisos del sistema de archivos se pueden solicitar como una cadena para el acceso de solo lectura o 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 el permiso {fileSystem: [ "write" ] }
:
"permissions": [
"storage",
"alarms",
"notifications",
"webview",
"<all_urls>",
{ "fileSystem": ["write"] }
],
Actualiza la vista en HTML
En index.html, agrega un botón Exportar a disco y un div
en el que 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>
Crea una 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 a disco y stubs para getTodosAsText()
, exportToFileEntry
y doExportToDisk()
.
Cómo obtener elementos de tareas pendientes como texto
Actualiza getTodosAsText()
para que lea todos de chrome.storage.local
y genere una representación textual 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 parámetro es un método de devolución de llamada.
Si ya hay un FileEntry
guardado, úsalo cuando llames a exportToFileEntry()
. Las referencias de archivo existen durante el ciclo de vida del objeto que representa el FileEntry
. En este ejemplo, se vincula FileEntry
a la ventana de la app para que el código de JavaScript pueda escribir en el archivo seleccionado sin ninguna interacción del usuario, siempre que la ventana de la app permanezca abierta.
Usa FileEntry para escribir todos los elementos en el disco
Actualiza exportToFileEntry()
para guardar las tareas pendientes 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 acceso al archivo visible que se muestra en el estado div
.
Usa fileEntry.createWriter()
para crear un objeto FileWriter
. Luego, fileWriter.write()
puede escribir
un Blob en el sistema de archivos. Usa fileWriter.onwriteend()
y fileWriter.onerror()
para actualizar el estado div
.
Para obtener más información sobre FileEntry
, lee Exploring the FileSystem APIs en HTML5Rocks o consulta FileEntry docs
en MDN.
Cómo conservar objetos FileEntry
Avanzado: Los objetos FileEntry
no se pueden conservar de forma indefinida. Tu app debe pedirle al usuario que elija un archivo cada vez que se inicie. Si tu app se reinició de forma forzosa debido a una falla o actualización del entorno de ejecución, restoreEntry() es una opción para restablecer un FileEntry
.
Si lo deseas, experimenta guardando el ID que muestra retainEntry() y restableciéndolo cuando se reinicie la app. (Sugerencia: Agrega un objeto de escucha al evento onRestarted
en la página en segundo plano).
Inicia la app de Todo terminada
Completaste el paso 6. Vuelve a cargar la app y agrega algunas tareas. Haz clic en Exportar a disco para exportar tus todos a un archivo .txt.
Más información
Para obtener información más detallada sobre algunas de las APIs que se presentan en este paso, consulta los siguientes recursos:
- Cómo usar la API de Chrome Filesystem ↑
- Declara los permisos ↑
- chrome.storage.local.get() ↑
- chrome.fileSystem.chooseEntry() ↑
- chrome.fileSystem.getDisplayPath() ↑
- chrome.fileSystem.restoreEntry() ↑
- chrome.fileSystem.retainEntry() ↑
¿Todo listo para continuar con el siguiente paso? Ve al Paso 7: Publica tu app ».