2010-09-08 11 views

Respuesta

328

Puede usar los URI de datos. El soporte del navegador varía; ver Wikipedia. Ejemplo:

<a href="data:application/octet-stream;charset=utf-16le;base64,//5mAG8AbwAgAGIAYQByAAoA">text file</a> 

La corriente de octeto consiste en forzar una solicitud de descarga. De lo contrario, probablemente se abrirá en el navegador.

Para CSV, puede utilizar:

<a href="data:application/octet-stream,field1%2Cfield2%0Afoo%2Cbar%0Agoo%2Cgai%0A">CSV Octet</a> 

Prueba el jsFiddle demo.

+12

Esto no es una solución de navegadores, pero definitivamente algo digno de mirar. Por ejemplo, IE limita el soporte a datos uri. IE 8 limita el tamaño a 32 KB e IE 7 e inferior no es compatible en absoluto. –

+0

@Darin, sí, esto no funcionará en ninguna versión de IE, porque los URI de datos no están permitidos en los elementos 'a'. –

+6

en la versión de Chrome 19.0.1084.46, este método genera la siguiente advertencia: "Recurso interpretado como documento pero transferido con tipo MIME text/csv:" data: text/csv, field1% 2Cfield2% 0Afoo% 2Cbar% 0Agoo% 2Cgai% 0A " " No se desencadena una descarga – Chris

-29

En realidad ES posible - use Flash.

Puede generar el contenido con JS y luego inicializar algunos flash vars o simplemente hacer todo dentro de una película flash.

Por favor, eche un vistazo a this para algunos comentarios importantes.

+0

Por favor, eche un vistazo a este hilo: http://stackoverflow.com/questions/1811736/can-flash-action-script-read-and-write-local-file-system –

+3

Debería haber especificado esto en mi pregunta , pero estoy buscando una solución nativa. De lo contrario, podría usar ActiveX (aunque solo funcionará en IE). –

+0

Creo que dicha funcionalidad está bloqueada intencionalmente –

-20

Si el archivo contiene datos de texto, una técnica que uso es poner el texto en un elemento textarea y hacer que el usuario lo seleccione (haga clic en textarea y luego ctrl-A) y luego copie y pegue en un editor de texto.

+27

Lo había considerado, pero desde un punto de fácil uso, esto es desastroso. Además, el archivo debe guardarse con una extensión CSV. Trata de decírselo a tus usuarios. –

1

Incluso puede hacer uno mejor que solo URI: con Chrome también puede sugerir el nombre del archivo, como se explica en this blog post about naming a download when using URIs.

+0

[@earcam publicó esto aquí hace casi un año] (http://stackoverflow.com/questions/3665115/create-a-file-in-memory-for-user-to-download-not-through-server/15856045 # comment-16342145). –

90

Estoy felizmente usando FileSaver.js. Su compatibilidad es bastante buena (IE10 + y todo lo demás), y es muy fácil de usar:

var blob = new Blob(["some text"], { 
    type: "text/plain;charset=utf-8;", 
}); 
saveAs(blob, "thing.txt"); 
+13

Desafortunadamente, IE10 + es un poco empinado ... –

+0

Esto funciona muy bien en Chrome. ¿Cómo permito que el usuario especifique la ubicación del archivo en el disco? – gregm

+5

Guau, gracias por la biblioteca fácil de usar. Esta es fácilmente la mejor respuesta, y ¿a quién le importan las personas que usan HTML <5 hoy en día? –

478

solución simple para navegadores listos HTML5 ...

function download(filename, text) { 
 
    var element = document.createElement('a'); 
 
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); 
 
    element.setAttribute('download', filename); 
 

 
    element.style.display = 'none'; 
 
    document.body.appendChild(element); 
 

 
    element.click(); 
 

 
    document.body.removeChild(element); 
 
}
form * { 
 
    display: block; 
 
    margin: 10px; 
 
}
<form onsubmit="download(this['name'].value, this['text'].value)"> 
 
    <input type="text" name="name" value="test.txt"> 
 
    <textarea name="text"></textarea> 
 
    <input type="submit" value="Download"> 
 
</form>

Uso

download('test.txt', 'Hello world!'); 
+5

Sí. Esto es exactamente lo que @MatthewFlaschen ha [publicado aquí hace 3 años] (http://stackoverflow.com/questions/3665115/create-a-file-in-memory-for-user-to-download-not-through- servidor/18197341? noredirect = 1 # answer-3665147). –

+32

Sí, pero con el atributo 'download' puede especificar el nombre del archivo ;-) –

+1

Como @earcam ya ha señalado [en los comentarios anteriores] (http://stackoverflow.com/questions/3665115/create-a-file- in-memory-for-user-to-download-not-through-server/18197341? noredirect = 1 # comment-16342145). –

4

solución que funciona en IE10: (necesitaba un archivo csv, pero es suficiente para cambiar el tipo y nombre de archivo de txt)

var csvContent=data; //here we load our csv data 
var blob = new Blob([csvContent],{ 
    type: "text/csv;charset=utf-8;" 
}); 

navigator.msSaveBlob(blob, "filename.csv") 
+0

[Respuesta de Ludovic] (http://stackoverflow.com/questions/3665115/create-a-file-in-memory-for-user-to-download-not-through-server/33542499 # 33542499) incluye este soporte grande y adicional para los otros navegadores. –

132

Todo el ejemplo anterior funciona bien en Chrome e IE, pero fallan en Firefox. Considere agregar un anclaje al cuerpo y extraerlo después de hacer clic.

var a = window.document.createElement('a'); 
a.href = window.URL.createObjectURL(new Blob(['Test,Text'], {type: 'text/csv'})); 
a.download = 'test.csv'; 

// Append anchor to body. 
document.body.appendChild(a); 
a.click(); 

// Remove anchor from body 
document.body.removeChild(a); 
+4

Sin embargo, hay [un error abierto en IE 10 (y todavía lo veo en 11)] (https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob- url-as-cross-origin-and-denies-access) que arroja "Acceso denegado" en la línea 'a.click()' porque cree que la URL blob es de origen cruzado. – Matt

+0

@Matt data uri es de origen cruzado en algunos navegadores. por lo que sé, no solo en msie, sino también en cromo. puedes probarlo intentando inyectar javascript con datos uri. No podrá acceder a otras partes del sitio ... – inf3rno

15

El siguiente método funciona en IE11 +, Firefox y Chrome 25+ 30+:

<a id="export" class="myButton" download="" href="#">export</a> 
<script> 
    function createDownloadLink(anchorSelector, str, fileName){ 
     if(window.navigator.msSaveOrOpenBlob) { 
      var fileData = [str]; 
      blobObject = new Blob(fileData); 
      $(anchorSelector).click(function(){ 
       window.navigator.msSaveOrOpenBlob(blobObject, fileName); 
      }); 
     } else { 
      var url = "data:text/plain;charset=utf-8," + encodeURIComponent(str); 
      $(anchorSelector).attr("download", fileName);    
      $(anchorSelector).attr("href", url); 
     } 
    } 

    $(function() { 
     var str = "hi,file"; 
     createDownloadLink("#export",str,"file.txt"); 
    }); 

</script> 

ver esto en acción: http://jsfiddle.net/Kg7eA/

Firefox y Chrome URI de datos de apoyo para la navegación, que permite nosotros para crear archivos navegando a un URI de datos, mientras que IE no lo admite por razones de seguridad.

Por otro lado, IE tiene API para guardar un blob, que se puede usar para crear y descargar archivos.

+0

Esto requiere jQuery. –

+0

Acabo de utilizar jquery para adjuntar eventos (onclick y onready) y establecer atributos, que también puede hacer con vanilla JS. La parte central (window.navigator.msSaveOrOpenBlob) no necesita jquery. –

+0

Todavía existe la limitación de tamaño para el enfoque de datos uri, ¿no? – flipperweid

6

Si lo que desea es convertir una cadena a estar disponible para su descarga puede probar esta usando jQuery.

$('a.download').attr('href', 'data:application/csv;charset=utf-8,' + encodeURI(data)); 
+0

Es posible que se necesiten datos de Scape con encodeURI como sugerí aquí antes de poder comentar: http://stackoverflow.com/a/32441536/4928558 – atfornes

3
var element = document.createElement('a'); 
element.setAttribute('href', 'data:text/text;charset=utf-8,' +  encodeURI(data)); 
element.setAttribute('download', "fileName.txt"); 
element.click(); 
+1

¿Cuáles son las diferencias entre este enfoque y la creación de un Blob? –

5

Esta solución se extrae directamente desde el repositorio github de tiddlywiki (tiddlywiki.com). He utilizado tiddlywiki en casi todos los navegadores y funciona como un encanto:

function(filename,text){ 
    // Set up the link 
    var link = document.createElement("a"); 
    link.setAttribute("target","_blank"); 
    if(Blob !== undefined) { 
     var blob = new Blob([text], {type: "text/plain"}); 
     link.setAttribute("href", URL.createObjectURL(blob)); 
    } else { 
     link.setAttribute("href","data:text/plain," + encodeURIComponent(text)); 
    } 
    link.setAttribute("download",filename); 
    document.body.appendChild(link); 
    link.click(); 
    document.body.removeChild(link); 
} 

Github repo: Download saver module

+0

Funciona muy bien en Chrome, pero no en Firefox. Hace un archivo y lo descarga, pero el archivo está vacío. Sin contenido. ¿Alguna idea de por qué? No lo he probado en IE ... – Narxx

2

Basado en @Rick respuesta que fue muy útil.

Tienes que escapar de la cadena data si desea compartir de esta manera:

$('a.download').attr('href', 'data:application/csv;charset=utf-8,'+ encodeURI(data)); 

` Lo siento, no puedo comentar sobre la respuesta de Rick @ debido a mi baja reputación actual en StackOverflow.

Un edit suggestion fue compartido y rechazado.

+1

No he podido aceptar la sugerencia. Extraño ... Actualicé el código. – Rick

114

Todas las soluciones anteriores no funcionaron en todos los navegadores. Esto es lo que finalmente funciona en IE 10+, Firefox y Chrome (y sin jQuery o cualquier otra biblioteca):

save: function(filename, data) { 
    var blob = new Blob([data], {type: 'text/csv'}); 
    if(window.navigator.msSaveOrOpenBlob) { 
     window.navigator.msSaveBlob(blob, filename); 
    } 
    else{ 
     var elem = window.document.createElement('a'); 
     elem.href = window.URL.createObjectURL(blob); 
     elem.download = filename;   
     document.body.appendChild(elem); 
     elem.click();   
     document.body.removeChild(elem); 
    } 
} 

Tenga en cuenta que, dependiendo de su situación, también puede llamar a URL.revokeObjectURL después de retirar elem . De acuerdo con la documentación para URL.createObjectURL:

cada vez que llame createObjectURL(), se crea un nuevo objeto URL, incluso si ya ha creado una para el mismo objeto. Cada uno de estos debe liberarse llamando a URL.revokeObjectURL() cuando ya no los necesite. Los navegadores lanzarán estos automáticamente cuando el documento esté descargado; sin embargo, para un rendimiento óptimo y uso de la memoria, si hay momentos seguros en los que puede descargarlos explícitamente, debe hacerlo.

+3

Gracias un millón. He intentado todos los ejemplos enumerados aquí y solo este funciona con cualquier navegador. Esta debería ser la respuesta aceptada. – LEM

+0

En Chrome, en realidad no tuve que agregar el elemento al cuerpo para que funcione. – JackMorrissey

+0

Hay un límite de tamaño. Para Chrome, se dice que es de 2 MB. ¿Alguien tiene idea de cómo lidiar con un archivo más grande? – gm2008

1

Según lo mencionado sobre filesaver es un paquete de parrilla para trabajar con archivos en el lado del cliente. Pero no es bueno tratar con archivos grandes. StreamSaver.js es una solución alternativa (que se señaló en FileServer.js) para tratar con archivos de gran tamaño:

const fileStream = streamSaver.createWriteStream('filename.txt', size); 
const writer = fileStream.getWriter(); 
for(var i = 0; i < 100; i++){ 
    var uint8array = new TextEncoder("utf-8").encode("Plain Text"); 
    writer.write(uint8array); 
} 
writer.close() 
+1

Text Encoder es muy experimental en este momento, sugiero evitarlo (o rellenarlo). –

Cuestiones relacionadas