{"id":81610,"date":"2022-07-28T15:39:45","date_gmt":"2022-07-28T13:39:45","guid":{"rendered":"https:\/\/rmarketingdigital.com\/development\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/"},"modified":"2021-07-06T10:13:40","modified_gmt":"2021-07-06T08:13:40","slug":"leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs","status":"publish","type":"post","link":"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/","title":{"rendered":"Reading and writing files and directories with the browser-nativefs library"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_86 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Contenidos<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#La-forma-tradicional-de-tratar-los-archivos\" >La forma tradicional de tratar los archivos<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Abrir-archivos\" >Abrir archivos<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Abrir-directorios\" >Abrir directorios<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Guardar-mas-bien-descargar-archivos\" >Guardar (m\u00e1s bien: descargar) archivos<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#El-problema\" >El problema<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#La-API-del-sistema-de-archivos-nativo\" >La API del sistema de archivos nativo<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Abrir-archivos-2\" >Abrir archivos<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Abrir-directorios-2\" >Abrir directorios<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Guardar-archivos\" >Guardar archivos<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Presentacion-de-browser-nativefs\" >Presentaci\u00f3n de browser-nativefs<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Filosofia-de-diseno\" >Filosof\u00eda de dise\u00f1o<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Utilizando-la-biblioteca-browser-nativefs\" >Utilizando la biblioteca browser-nativefs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Manifestacion\" >Manifestaci\u00f3n<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#La-biblioteca-browser-nativefs-en-la-naturaleza\" >La biblioteca browser-nativefs en la naturaleza<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Ejemplo-de-codigo-de-la-vida-real\" >Ejemplo de c\u00f3digo de la vida real<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Consideraciones-sobre-la-interfaz-de-usuario\" >Consideraciones sobre la interfaz de usuario<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Conclusiones\" >Conclusiones<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#Agradecimientos\" >Agradecimientos<\/a><\/li><\/ul><\/nav><\/div>\n<p><\/p>\n<div>\n<header class=\"w-article-header\">\n<p>\n          <time>27 de julio de 2020<\/time><\/p>\n<\/header>\n<p>Los navegadores han podido tratar con archivos y directorios por mucho tiempo.  los <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/w3c.github.io\/FileAPI\/\">API de archivos<\/a><br \/>\nproporciona funciones para representar objetos de archivo en aplicaciones web, as\u00ed como para seleccionarlos a trav\u00e9s de programaci\u00f3n y ingresar a sus datos.  A pesar de todo, en el momento en que miras m\u00e1s de cerca, todo lo que brilla no es oro.<\/p>\n<h2 id=\"the-traditional-way-of-dealing-with-files\"><span class=\"ez-toc-section\" id=\"La-forma-tradicional-de-tratar-los-archivos\"><\/span>La forma tradicional de tratar los archivos <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3 id=\"opening-files\"><span class=\"ez-toc-section\" id=\"Abrir-archivos\"><\/span>Abrir archivos <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Como desarrollador, puede abrir y leer archivos a trav\u00e9s del<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/input\/file\"><code>&lt;input type=\"file\"&gt;<\/code><\/a><\/p>\n<p>elemento.  En su forma m\u00e1s simple, abrir un archivo puede parecerse al ejemplo de c\u00f3digo siguiente.  los <code>input<\/code> el objeto te da un <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/FileList\"><code>FileList<\/code><\/a>, que en el caso siguiente consta de solo una<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/File\"><code>File<\/code><\/a>.  UNA <code>File<\/code> es un tipo espec\u00edfico de <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Blob\"><code>Blob<\/code><\/a>, y se puede utilizar en cualquier contexto que un Blob pueda.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">openFile<\/span> <span class=\"token operator\">=<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">return<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">Promise<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">resolve<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">const<\/span> input <span class=\"token operator\">=<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">createElement<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'input'<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br>input<span class=\"token punctuation\">.<\/span>type <span class=\"token operator\">=<\/span> <span class=\"token string\">'file'<\/span><span class=\"token punctuation\">;<\/span><br>input<span class=\"token punctuation\">.<\/span><span class=\"token function\">addEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'change'<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token function\">resolve<\/span><span class=\"token punctuation\">(<\/span>input<span class=\"token punctuation\">.<\/span>files<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br>input<span class=\"token punctuation\">.<\/span><span class=\"token function\">click<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<h3 id=\"opening-directories\"><span class=\"ez-toc-section\" id=\"Abrir-directorios\"><\/span>Abrir directorios <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Para abrir carpetas (o directorios), puede configurar el<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/input#attr-webkitdirectory\"><code>&lt;input webkitdirectory&gt;<\/code><\/a><\/p>\n<p>atributo.  Aparte de eso, todo lo dem\u00e1s funciona igual que arriba.  Pese a su nombre con prefijo de proveedor,<br \/>\n<code>webkitdirectory<\/code> no solo se puede usar en los navegadores Chromium y WebKit, sino adem\u00e1s en el Edge heredado basado en EdgeHTML y en Firefox.<\/p>\n<h3 id=\"saving-(rather:-downloading)-files\"><span class=\"ez-toc-section\" id=\"Guardar-mas-bien-descargar-archivos\"><\/span>Guardar (m\u00e1s bien: descargar) archivos <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Para almacenar un archivo, tradicionalmente, est\u00e1 limitado a <em>descargando<\/em> un archivo, que funciona gracias a la<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/a#attr-download:~:text=download\"><code>&lt;a download&gt;<\/code><\/a><\/p>\n<p>atributo.  Dado un Blob, puede determinar el ancla <code>href<\/code> atribuir a un <code>blob:<\/code> URL que puede conseguir del<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/URL\/createObjectURL\"><code>URL.createObjectURL()<\/code><\/a><\/p>\n<p>m\u00e9todo.<\/p>\n<div class=\"w-aside w-aside--caution\">\n<p><strong>Precauci\u00f3n:<\/strong><br \/>\nPara evitar p\u00e9rdidas de memoria, siempre revoque la URL luego de la descarga.<\/p>\n<\/div>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">saveFile<\/span> <span class=\"token operator\">=<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">blob<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">const<\/span> a <span class=\"token operator\">=<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">createElement<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'a'<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br>a<span class=\"token punctuation\">.<\/span>download <span class=\"token operator\">=<\/span> <span class=\"token string\">'my-file.txt'<\/span><span class=\"token punctuation\">;<\/span><br>a<span class=\"token punctuation\">.<\/span>href <span class=\"token operator\">=<\/span> <span class=\"token constant\">URL<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">createObjectURL<\/span><span class=\"token punctuation\">(<\/span>blob<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br>a<span class=\"token punctuation\">.<\/span><span class=\"token function\">addEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'click'<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">e<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token function\">setTimeout<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token constant\">URL<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">revokeObjectURL<\/span><span class=\"token punctuation\">(<\/span>a<span class=\"token punctuation\">.<\/span>href<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">30<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">1000<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br>a<span class=\"token punctuation\">.<\/span><span class=\"token function\">click<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<h3 id=\"the-problem\"><span class=\"ez-toc-section\" id=\"El-problema\"><\/span>El problema <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Una desventaja masiva del <em>descargar<\/em> enfoque es que no hay forma de hacer que suceda un flujo cl\u00e1sico de abrir \u2192 editar \u2192 guardar, dicho de otra forma, no hay forma de <em>Sobrescribir<\/em> el archivo original.  En cambio, terminas con un nuevo <em>Copiar<\/em> del archivo original en la carpeta de descargas predeterminada del sistema operativo cada vez que \u00abguarde\u00bb.<\/p>\n<h2 id=\"the-native-file-system-api\"><span class=\"ez-toc-section\" id=\"La-API-del-sistema-de-archivos-nativo\"><\/span>La API del sistema de archivos nativo <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>La API del sistema de archivos nativo hace que ambas operaciones, abrir y guardar, sean mucho m\u00e1s sencillas.  Adem\u00e1s posibilita <em>verdadero ahorro<\/em>, dicho de otra forma, no solo puede optar d\u00f3nde guardar un archivo, sino adem\u00e1s sobrescribir un archivo existente.<\/p>\n<h3 id=\"opening-files-2\"><span class=\"ez-toc-section\" id=\"Abrir-archivos-2\"><\/span>Abrir archivos <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Con el <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/wicg.github.io\/native-file-system\/\">API del sistema de archivos nativo<\/a>, abrir un archivo es cuesti\u00f3n de una llamada al <code>window.showOpenFilePicker()<\/code> m\u00e9todo.  Esta llamada devuelve un identificador de archivo, del cual puede conseguir el <code>File<\/code> a trav\u00e9s de el <code>getFile()<\/code> m\u00e9todo.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">openFile<\/span> <span class=\"token operator\">=<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>handle<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> window<span class=\"token punctuation\">.<\/span> <span class=\"token function\">showOpenFilePicker<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">return<\/span> handle<span class=\"token punctuation\">.<\/span><span class=\"token function\">getFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>err<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br>console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span>err<span class=\"token punctuation\">.<\/span>name<span class=\"token punctuation\">,<\/span> err<span class=\"token punctuation\">.<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<h3 id=\"opening-directories-2\"><span class=\"ez-toc-section\" id=\"Abrir-directorios-2\"><\/span>Abrir directorios <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Abra un directorio llamando<br \/>\n<code>window.showDirectoryPicker()<\/code> que hace que los directorios se puedan elegir en el cuadro de di\u00e1logo del archivo.<\/p>\n<h3 id=\"saving-files\"><span class=\"ez-toc-section\" id=\"Guardar-archivos\"><\/span>Guardar archivos <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Guardar archivos es igualmente sencillo.  Desde un identificador de archivo, crea una secuencia de escritura mediante <code>createWritable()<\/code>, despu\u00e9s escribe los datos de Blob llamando al flujo <code>write()<\/code> m\u00e9todo, y en conclusi\u00f3n cierra la secuencia llamando a su <code>close()<\/code> m\u00e9todo.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">saveFile<\/span> <span class=\"token operator\">=<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">blob<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">const<\/span> handle <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> window<span class=\"token punctuation\">.<\/span><span class=\"token function\">showSaveFilePicker<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br>types<span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">{<\/span><br>accept<span class=\"token operator\">:<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">const<\/span> writable <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> handle<span class=\"token punctuation\">.<\/span><span class=\"token function\">createWritable<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">await<\/span> writable<span class=\"token punctuation\">.<\/span><span class=\"token function\">write<\/span><span class=\"token punctuation\">(<\/span>blob<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">await<\/span> writable<span class=\"token punctuation\">.<\/span><span class=\"token function\">close<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">return<\/span> handle<span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>err<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br>console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span>err<span class=\"token punctuation\">.<\/span>name<span class=\"token punctuation\">,<\/span> err<span class=\"token punctuation\">.<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<h2 id=\"introducing-browser-nativefs\"><span class=\"ez-toc-section\" id=\"Presentacion-de-browser-nativefs\"><\/span>Presentaci\u00f3n de browser-nativefs <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Tan estupendamente bien como la API del sistema de archivos nativo, es <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/caniuse.com\/#feat=native-filesystem-api\">todav\u00eda no ampliamente disponible<\/a>.<\/p>\n<figure class=\"w-figure\">\n  <img alt='caniuse-5305250' class=\"w-screenshot\" src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/caniuse-5305250.png' alt=\"Tabla de compatibilidad del navegador para la API del sistema de archivos nativo.  Todos los navegadores est\u00e1n marcados como 'sin soporte' o 'detr\u00e1s de una bandera'.\"><figcaption class=\"w-figcaption\">\n<p>    Tabla de compatibilidad del navegador para la API del sistema de archivos nativo.  (<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/caniuse.com\/#feat=native-filesystem-api\">Fuente<\/a>)<br \/>\n  <\/figcaption><\/figure>\n<p>Es es por esto que que veo la API del sistema de archivos nativo como una mejora progresiva.  Como tal, quiero usarlo cuando el navegador lo admita, y utilizar el enfoque tradicional si no;  todo ello sin castigar nunca al usuario con descargas innecesarias de c\u00f3digo JavaScript no compatible.  los <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/GoogleChromeLabs\/browser-nativefs\">browser-nativefs<\/a><br \/>\nLibrary es mi respuesta a este reto.<\/p>\n<h3 id=\"design-philosophy\"><span class=\"ez-toc-section\" id=\"Filosofia-de-diseno\"><\/span>Filosof\u00eda de dise\u00f1o <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Ya que es probable que la API del sistema de archivos nativo cambie en el futuro, la API del browser-nativefs no se basa en ella.  Dicho de otra forma, la biblioteca no es un <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/Polyfill\">polyfill<\/a>, sino m\u00e1s bien un <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/sindresorhus\/ponyfill\">ponyfill<\/a>.  Puede (est\u00e1tica o din\u00e1micamente) importar exclusivamente cualquier funcionalidad que necesite para mantener su aplicaci\u00f3n lo m\u00e1s peque\u00f1a viable.  Los m\u00e9todos disponibles son los apropiadamente nombrados<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/GoogleChromeLabs\/browser-nativefs#opening-files\"><code>fileOpen()<\/code><\/a>,<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/GoogleChromeLabs\/browser-nativefs#opening-directories\"><code>directoryOpen()<\/code><\/a>y<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/GoogleChromeLabs\/browser-nativefs#saving-files\"><code>fileSave()<\/code><\/a>.  Internamente, la funci\u00f3n de biblioteca detecta si la API del sistema de archivos nativo es compatible y despu\u00e9s importa la ruta del c\u00f3digo respectivo.<\/p>\n<h3 id=\"using-the-browser-nativefs-library\"><span class=\"ez-toc-section\" id=\"Utilizando-la-biblioteca-browser-nativefs\"><\/span>Utilizando la biblioteca browser-nativefs <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Los tres m\u00e9todos son intuitivos de utilizar.  Puede especificar la aceptaci\u00f3n de su aplicaci\u00f3n <code>mimeTypes<\/code> o archivo <code>extensions<\/code>y establezca un <code>multiple<\/code> marca para permitir o no permitir la selecci\u00f3n de varios archivos o directorios.  Para conseguir detalles completos, consulte el<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/GoogleChromeLabs\/browser-nativefs#api-documentation\">documentaci\u00f3n de la API del browser-nativefs<\/a>.  El siguiente ejemplo de c\u00f3digo muestra c\u00f3mo puede abrir y guardar archivos de imagen.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><br><span class=\"token keyword\">import<\/span> <span class=\"token punctuation\">{<\/span><br>fileOpen<span class=\"token punctuation\">,<\/span><br>directoryOpen<span class=\"token punctuation\">,<\/span><br>fileSave<span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">from<\/span> <span class=\"token string\">'https:\/\/unpkg.com\/browser-nativefs'<\/span><span class=\"token punctuation\">;<\/span><p><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">const<\/span> blob <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> <span class=\"token function\">fileOpen<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br>mimeTypes<span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">'image\/*'<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p><p><br><span class=\"token keyword\">const<\/span> blobs <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> <span class=\"token function\">fileOpen<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br>mimeTypes<span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">'image\/*'<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br>multiple<span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p><p><br><span class=\"token keyword\">const<\/span> blobsInDirectory <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> <span class=\"token function\">directoryOpen<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br>recursive<span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p><p><br><span class=\"token keyword\">await<\/span> <span class=\"token function\">fileSave<\/span><span class=\"token punctuation\">(<\/span>blob<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br>fileName<span class=\"token operator\">:<\/span> <span class=\"token string\">'Untitled.png'<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<h3 id=\"demo\"><span class=\"ez-toc-section\" id=\"Manifestacion\"><\/span>Manifestaci\u00f3n <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Puede ver el c\u00f3digo anterior en acci\u00f3n en un <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/browser-nativefs.glitch.me\/\">manifestaci\u00f3n<\/a> en Glitch.  Sus <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/glitch.com\/edit\/#!\/browser-nativefs\">c\u00f3digo fuente<\/a> adem\u00e1s se encuentra disponible all\u00ed.  Ya que, por razones de seguridad, los subtramas de origen cruzado no pueden mostrar un selector de archivos, la demostraci\u00f3n no se puede incrustar en este post.<\/p>\n<h2 id=\"the-browser-nativefs-library-in-the-wild\"><span class=\"ez-toc-section\" id=\"La-biblioteca-browser-nativefs-en-la-naturaleza\"><\/span>La biblioteca browser-nativefs en la naturaleza <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>En mi tiempo libre, contribuyo un poquito a una PWA instalable llamada <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/excalidraw.com\/\">Excalidraw<\/a>, una herramienta de pizarra que le posibilita esbozar diagramas f\u00e1cilmente con una sensaci\u00f3n de dibujado a mano.  Es completamente sensible y va bastante bien en una gama de dispositivos, desde peque\u00f1os tel\u00e9fonos m\u00f3viles hasta computadoras con pantallas grandes.  Esto significa que debe manejar archivos en todas las diversas plataformas, ya sea que admitan o no la API del sistema de archivos nativo.  Esto lo convierte en un gran candidato para la biblioteca browser-nativefs.<\/p>\n<p>Puedo, a modo de ejemplo, iniciar un dibujo en mi iPhone, guardarlo (t\u00e9cnicamente: descargarlo, dado que Safari no es compatible con la API del sistema de archivos nativo) en la carpeta Descargas de mi iPhone, abrir el archivo en mi escritorio (luego de transferirlo desde mi phone), modificar el archivo y sobrescribirlo con mis cambios, o inclusive guardarlo como un archivo nuevo.<\/p>\n<figure class=\"w-figure\">\n  <img alt='iphone-original-5647631' class=\"w-screenshot\" src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/iphone-original-5647631.png' width=\"300\" alt=\"Un dibujo de Excalidraw en un iPhone.\"><figcaption class=\"w-figcaption\">\n<p>    Iniciar un dibujo de Excalidraw en un iPhone donde la API del sistema de archivos nativo no es compatible, pero donde se puede guardar (descargar) un archivo en la carpeta Descargas).<br \/>\n  <\/figcaption><\/figure>\n<figure class=\"w-figure\">\n  <img alt='chrome-modify-4721146' class=\"w-screenshot\" src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/chrome-modify-4721146.png' alt=\"El dibujo de Excalidraw modificado en Chrome en el escritorio.\"><figcaption class=\"w-figcaption\">\n<p>    Abrir y modificar el dibujo de Excalidraw en el escritorio donde se admite la API del sistema de archivos nativo y, de este modo, se puede ingresar al archivo mediante la API.<br \/>\n  <\/figcaption><\/figure>\n<figure class=\"w-figure\">\n  <img alt='chrome-oversave-2788546' class=\"w-screenshot\" src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/chrome-oversave-2788546.png' alt=\"Sobrescribiendo el archivo original con las modificaciones.\"><figcaption class=\"w-figcaption\">\n<p>    Sobrescribiendo el archivo original con las modificaciones al archivo de dibujo original de Excalidraw.  El navegador muestra un cuadro de di\u00e1logo que me pregunta si est\u00e1 bien.<br \/>\n  <\/figcaption><\/figure>\n<figure class=\"w-figure\">\n  <img alt='chrome-save-as-8162641' class=\"w-screenshot\" src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/chrome-save-as-8162641.png' alt=\"Guardar las modificaciones en un nuevo archivo de dibujo de Excalidraw.\"><figcaption class=\"w-figcaption\">\n<p>    Guardar las modificaciones en un nuevo archivo Excalidraw.  El archivo original permanece intacto.<br \/>\n  <\/figcaption><\/figure>\n<h3 id=\"real-life-code-sample\"><span class=\"ez-toc-section\" id=\"Ejemplo-de-codigo-de-la-vida-real\"><\/span>Ejemplo de c\u00f3digo de la vida real <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>A continuaci\u00f3n, puede ver un ejemplo real de browser-nativefs tal como se utiliza en Excalidraw.  Este extracto est\u00e1 tomado de<br \/>\n<code>\/src\/data\/json.ts<\/code>.  De especial inter\u00e9s es c\u00f3mo <code>saveAsJSON()<\/code> pasa un identificador de archivo o <code>null<\/code> a browser-nativefs &#8216;<br \/>\n<code>fileSave()<\/code> , que hace que se sobrescriba cuando se le asigna un identificador, o que se guarde en un nuevo archivo si no es as\u00ed.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">saveAsJSON<\/span> <span class=\"token operator\">=<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">(<\/span><br><span class=\"token parameter\">elements<span class=\"token operator\">:<\/span> readonly ExcalidrawElement<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br>appState<span class=\"token operator\">:<\/span> AppState<span class=\"token punctuation\">,<\/span><br>fileHandle<span class=\"token operator\">:<\/span> any<span class=\"token punctuation\">,<\/span><\/span><br><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">const<\/span> serialized <span class=\"token operator\">=<\/span> <span class=\"token function\">serializeAsJSON<\/span><span class=\"token punctuation\">(<\/span>elements<span class=\"token punctuation\">,<\/span> appState<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">const<\/span> blob <span class=\"token operator\">=<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">Blob<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">[<\/span>serialized<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br>type<span class=\"token operator\">:<\/span> <span class=\"token string\">\"application\/json\"<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">const<\/span> name <span class=\"token operator\">=<\/span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`<\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>appState<span class=\"token punctuation\">.<\/span>name<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token string\">.excalidraw<\/span><span class=\"token template-punctuation string\">`<\/span><\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">(<\/span>window <span class=\"token keyword\">as<\/span> any<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>handle <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> <span class=\"token function\">fileSave<\/span><span class=\"token punctuation\">(<\/span><br>blob<span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">{<\/span><br>fileName<span class=\"token operator\">:<\/span> name<span class=\"token punctuation\">,<\/span><br>description<span class=\"token operator\">:<\/span> <span class=\"token string\">\"Excalidraw file\"<\/span><span class=\"token punctuation\">,<\/span><br>extensions<span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"excalidraw\"<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br>fileHandle <span class=\"token operator\">||<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><p><span class=\"token keyword\">export<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">loadFromJSON<\/span> <span class=\"token operator\">=<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">const<\/span> blob <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> <span class=\"token function\">fileOpen<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br>description<span class=\"token operator\">:<\/span> <span class=\"token string\">\"Excalidraw files\"<\/span><span class=\"token punctuation\">,<\/span><br>extensions<span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"json\"<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">\"excalidraw\"<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br>mimeTypes<span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"application\/json\"<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">return<\/span> <span class=\"token function\">loadFromBlob<\/span><span class=\"token punctuation\">(<\/span>blob<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<h3 id=\"ui-considerations\"><span class=\"ez-toc-section\" id=\"Consideraciones-sobre-la-interfaz-de-usuario\"><\/span>Consideraciones sobre la interfaz de usuario <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Ya sea en Excalidraw o en su aplicaci\u00f3n, la interfaz de usuario debe adaptarse a la situaci\u00f3n de soporte del navegador.  Si se admite la API del sistema de archivos nativo (<code>if ('showOpenFilePicker' in window) {}<\/code>) puedes mostrar un <strong>Guardar como<\/strong> bot\u00f3n al mismo tiempo de un <strong>Salvar<\/strong> bot\u00f3n.  Las capturas de pantalla a continuaci\u00f3n muestran la diferencia entre la barra de herramientas de la aplicaci\u00f3n principal receptiva de Excalidraw en el iPhone y en el escritorio de Chrome.  Tenga en cuenta c\u00f3mo en iPhone el <strong>Guardar como<\/strong> Falta el bot\u00f3n.<\/p>\n<figure class=\"w-figure\">\n  <img alt='save-1154063' class=\"w-screenshot\" src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/save-1154063.png' alt=\"Barra de herramientas de la aplicaci\u00f3n Excalidraw en iPhone con solo un bot\u00f3n 'Guardar'.\" width=\"300\"><figcaption class=\"w-figcaption\">\n<p>    Barra de herramientas de la aplicaci\u00f3n Excalidraw en iPhone con solo un <strong>Salvar<\/strong> bot\u00f3n.<br \/>\n  <\/figcaption><\/figure>\n<figure class=\"w-figure\">\n  <img alt='save-save-as-7805564' class=\"w-screenshot\" src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/save-save-as-7805564.png' alt=\"Barra de herramientas de la aplicaci\u00f3n Excalidraw en el escritorio de Chrome con un bot\u00f3n 'Guardar' y un bot\u00f3n 'Guardar como'.\" width=\"300\"><figcaption class=\"w-figcaption\">\n<p>    Barra de herramientas de la aplicaci\u00f3n Excalidraw en Chrome con <strong>Salvar<\/strong> y un enfocado <strong>Guardar como<\/strong> bot\u00f3n.<br \/>\n  <\/figcaption><\/figure>\n<h2 id=\"conclusions\"><span class=\"ez-toc-section\" id=\"Conclusiones\"><\/span>Conclusiones <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Trabajar con archivos nativos t\u00e9cnicamente funciona en todos los navegadores modernos.  En los navegadores que admiten la API del sistema de archivos nativo, puede mejorar la experiencia al permitir el verdadero guardado y sobrescritura (no solo la descarga) de archivos y al permitir que sus usuarios creen nuevos archivos donde lo deseen, todo sin dejar de ser funcional en los navegadores que s\u00ed lo hacen. no es compatible con la API del sistema de archivos nativo.  los <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/GoogleChromeLabs\/browser-nativefs\">browser-nativefs<\/a> le facilita la vida al lidiar con las sutilezas de la mejora progresiva y hacer que su c\u00f3digo sea lo m\u00e1s simple viable.<\/p>\n<h2 id=\"acknowledgements\"><span class=\"ez-toc-section\" id=\"Agradecimientos\"><\/span>Agradecimientos <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Este post fue revisado por <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/jpmedley\">Joe Medley<\/a> y<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/kaycebasques\">Kayce vascos<\/a>.  Gracias a <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/excalidraw\/excalidraw\/graphs\/contributors\">colaboradores de Excalidraw<\/a><br \/>\npor su trabajo en el proyecto y por revisar mis Pull Requests.<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/unsplash.com\/photos\/hXrPSgGFpqQ\">Imagen de h\u00e9roe<\/a> por<br \/>\n<a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/unsplash.com\/@ilyapavlov\">Ilya Pavlov<\/a> en Unsplash.<\/p>\n<p>    <web-feedback additional-questions=\"api\"><\/web-feedback>\n  <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Jul 27, 2020 Browsers have been able to deal with files and directories for a long time. The File APIs provide functions for rendering file objects in applications\u2026<\/p>","protected":false},"author":1,"featured_media":81611,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1356],"tags":[],"class_list":["post-81610","post","type-post","status-publish","format-standard","has-post-thumbnail","category-dev"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.0 (Yoast SEO v28.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Leer y escribir archivos y directorios con la biblioteca browser-nativefs - R Marketing Digital<\/title>\n<meta name=\"description\" content=\"27 de julio de 2020 Los navegadores han podido tratar con archivos y directorios por mucho tiempo. los API de archivos proporciona funciones para\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Leer y escribir archivos y directorios con la biblioteca browser-nativefs\" \/>\n<meta property=\"og:description\" content=\"27 de julio de 2020 Los navegadores han podido tratar con archivos y directorios por mucho tiempo. los API de archivos proporciona funciones para\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/\" \/>\n<meta property=\"og:site_name\" content=\"R Marketing Digital\" \/>\n<meta property=\"article:published_time\" content=\"2022-07-28T13:39:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4794603.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"360\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"R Marketing Digital\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/\"},\"author\":{\"name\":\"R Marketing Digital\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\"},\"headline\":\"Leer y escribir archivos y directorios con la biblioteca browser-nativefs\",\"datePublished\":\"2022-07-28T13:39:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/\"},\"wordCount\":1403,\"image\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4794603.jpg\",\"articleSection\":[\"Dev\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/\",\"name\":\"Leer y escribir archivos y directorios con la biblioteca browser-nativefs - R Marketing Digital\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4794603.jpg\",\"datePublished\":\"2022-07-28T13:39:45+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\"},\"description\":\"27 de julio de 2020 Los navegadores han podido tratar con archivos y directorios por mucho tiempo. los API de archivos proporciona funciones para\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/dev\\\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\\\/#primaryimage\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4794603.jpg\",\"contentUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4794603.jpg\",\"width\":1200,\"height\":360,\"caption\":\"hero-4794603-5544132-jpg\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#website\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/\",\"name\":\"R Marketing Digital\",\"description\":\"Agencia SEO | Publicidad redes sociales | Community Management\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rmarketingdigital.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\",\"name\":\"R Marketing Digital\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"caption\":\"R Marketing Digital\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Read and write files and directories with the browser-nativefs library - R Marketing Digital","description":"Jul 27, 2020 Browsers have been able to deal with files and directories for a long time. The File API provides functions for","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/","og_locale":"en_US","og_type":"article","og_title":"Leer y escribir archivos y directorios con la biblioteca browser-nativefs","og_description":"27 de julio de 2020 Los navegadores han podido tratar con archivos y directorios por mucho tiempo. los API de archivos proporciona funciones para","og_url":"https:\/\/rmarketingdigital.com\/en\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/","og_site_name":"R Marketing Digital","article_published_time":"2022-07-28T13:39:45+00:00","og_image":[{"width":1200,"height":360,"url":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4794603.jpg","type":"image\/jpeg"}],"author":"R Marketing Digital","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#article","isPartOf":{"@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/"},"author":{"name":"R Marketing Digital","@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e"},"headline":"Leer y escribir archivos y directorios con la biblioteca browser-nativefs","datePublished":"2022-07-28T13:39:45+00:00","mainEntityOfPage":{"@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/"},"wordCount":1403,"image":{"@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#primaryimage"},"thumbnailUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4794603.jpg","articleSection":["Dev"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/","url":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/","name":"Read and write files and directories with the browser-nativefs library - R Marketing Digital","isPartOf":{"@id":"https:\/\/rmarketingdigital.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#primaryimage"},"image":{"@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#primaryimage"},"thumbnailUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4794603.jpg","datePublished":"2022-07-28T13:39:45+00:00","author":{"@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e"},"description":"Jul 27, 2020 Browsers have been able to deal with files and directories for a long time. The File API provides functions for","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rmarketingdigital.com\/dev\/leer-y-escribir-archivos-y-directorios-con-la-biblioteca-browser-nativefs\/#primaryimage","url":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4794603.jpg","contentUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4794603.jpg","width":1200,"height":360,"caption":"hero-4794603-5544132-jpg"},{"@type":"WebSite","@id":"https:\/\/rmarketingdigital.com\/#website","url":"https:\/\/rmarketingdigital.com\/","name":"R Digital Marketing","description":"SEO Agency | Advertising social networks | Community Management","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rmarketingdigital.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e","name":"R Digital Marketing","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","caption":"R Marketing Digital"}}]}},"_links":{"self":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/posts\/81610","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/comments?post=81610"}],"version-history":[{"count":0,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/posts\/81610\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/media\/81611"}],"wp:attachment":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/media?parent=81610"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/categories?post=81610"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/tags?post=81610"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}