La forma más sencilla de abrir una ventana de descarga sin salir de la página

118

¿Cuál es la mejor forma de varios navegadores para abrir un cuadro de diálogo de descarga (supongamos que podemos configurar la disposición de contenido: adjunto en los encabezados) sin navegar fuera de la página actual o abrir ventanas emergentes, lo cual no funciona bien en Internet Explorer (IE ) 6.

mkoryak
fuente

Respuestas:

106

Han pasado 7 años y no sé si funciona para IE6 o no, pero esto abre OpenFileDialog en FF y Chrome.

var file_path = 'host/path/file.ext';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
0x000f
fuente
Primero, gracias por esta solución, pero encontré un error si removeChild (a) el zip descomprimirá el error con zip está roto, así que elimine este código y resuélvalo
Roy
2
@Manoj Rana: he comprobado que FF 58.0.2 (64 bits) está funcionando. No funcionará en ningún FF si elimina 2 líneas document.body.appendChild (a); document.body.removeChild (a);
0x000f
1
Para que funcione en Edge 16, el encabezado, de donde proviene el archivo, debe contener Content-Type: application/octet-streamy Content-Disposition: attachment.
Simon
12
esto ya no funciona developers.google.com/web/updates/2018/02/…
Paulius Dragunas
2
@ user1933131 el cromo se elimina solo para el origen
cruzado
200

Este javascript es bueno porque no abre una nueva ventana o pestaña.

window.location.assign(url);
mozgras
fuente
17
Es lo mismo que window.location = url; "Siempre que se asigna un nuevo valor al objeto de ubicación, se cargará un documento utilizando la URL como si se hubiera llamado a window.location.assign () con la URL modificada" - developer.mozilla.org/en-US/docs/ Web / API / window.location
Rob Juurlink
13
Esto hace que la conexión WebSocket se desconecte.
igorpavlov
4
He usado la misma solución pero abre el archivo en la misma pestaña en lugar de abrir un diálogo de descarga.
Techno Cracker
2
es lo mismo para window.open (url, '_self') si la url es para la página de descarga entonces.
Experto quiere ser el
5
Al usar IE11, descubrí que esto hacía que JS se detuviera. Entonces, para IE 11 usé window.open (url, '_blank') que abrió otra pestaña, sin embargo, esa pestaña se cerró cuando funcionó que el archivo era una descarga. Esto mantuvo el JS funcionando.
Lucas
23

Siempre agrego un target = "_ blank" al enlace de descarga. Esto abrirá una nueva ventana, pero tan pronto como el usuario haga clic en Guardar, la nueva ventana se cerrará.

jao
fuente
2
Esta es la mejor respuesta. En Internet Explorer, agregar 'target = "_ blank"' a un enlace que se va a descargar evitará que el navegador navegue (donde se imprime "HTML1300: Navigation ocurrió") y, por lo tanto, puede dejar la página en un estado inconsistente.
user64141
23

Coloque esto en la sección de encabezado HTML, estableciendo la urlvar en la URL del archivo que se descargará:

<script type="text/javascript">  
function startDownload()  
{  
     var url='http://server/folder/file.ext';    
     window.open(url, 'Download');  
}  
</script>

Luego ponga esto en el cuerpo, que iniciará la descarga automáticamente después de 5 segundos:

<script type="text/javascript">  
setTimeout('startDownload()', 5000); //starts download after 5 seconds  
</script> 

(Desde aquí .)

George Claghorn
fuente
2
eso no funciona, porque en IE6, si el usuario hace clic en "guardar", el archivo se guarda, pero la ventana emergente permanece abierta. Esto no es aceptable.
mkoryak
este código no funciona en safari, ¿pueden ayudarme a resolverlo en safari?
Renish Khunt
17

Sé que se hizo la pregunta, 7 years and 9 months agopero muchas soluciones publicadas no parecen funcionar, por ejemplo, usar un <iframe>solo funciona con FireFoxy no funciona con Chrome.

Mejor solución:

La mejor solución de trabajo para abrir una ventana emergente de descarga de archivos JavaScriptes usar un HTMLelemento de enlace, sin necesidad de agregar el elemento de enlacedocument.body como se indica en otras respuestas.

Puede utilizar la siguiente función:

function downloadFile(filePath){
    var link=document.createElement('a');
    link.href = filePath;
    link.download = filePath.substr(filePath.lastIndexOf('/') + 1);
    link.click();
}

En mi aplicación, lo estoy usando de esta manera:

downloadFile('report/xls/myCustomReport.xlsx');

Demo de trabajo:

Nota:

  • Debe usar el link.downloadatributo para que el navegador no abra el archivo en una nueva pestaña y active la ventana emergente de descarga.
  • Esto se probó con varios tipos de archivos (docx, xlsx, png, pdf, ...).
cнŝdk
fuente
¿Cuál sería la mejor manera de mostrar un gif de carga hasta que se haya descargado el archivo?
Ctrl_Alt_Defeat
1
@Ctrl_Alt_Defeat Bueno, en este caso no será fácil rastrear el proceso de descarga, pero un truco puede ser mostrar esta animación gif al linkhacer clic y ocultarla después de un tiempo de espera, usando este código:, link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); }puede verlo funcionando en este violín , pero tenga en cuenta que no es una forma recomendada de hacerlo, se manejaría mejor si estuviéramos usando Ajax.
cнŝdk
1
no funciona en Firefox. ¿cómo descargar en firefox?
Manoj Rana
@ManojRana Para firefox, puede usar y iframever esta respuesta .
cнŝdk
2
Esta solución funciona en Chrome, Safari y Firefox para mí :)
ariebear
15

He estado buscando una buena forma de usar javascript para iniciar la descarga de un archivo, tal como sugiere esta pregunta. Sin embargo, estas respuestas no han sido útiles. Luego hice algunas pruebas de xbrowser y descubrí que un iframe funciona mejor en todos los navegadores modernos IE> 8.

downloadUrl = "http://example.com/download/file.zip";
var downloadFrame = document.createElement("iframe"); 
downloadFrame.setAttribute('src',downloadUrl);
downloadFrame.setAttribute('class',"screenReaderText"); 
document.body.appendChild(downloadFrame); 

class="screenReaderText" es mi clase para diseñar contenido que está presente pero no se puede ver.

css:

.screenReaderText { 
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; 
  margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px; 
}

igual que .visuallyHidden en html5boilerplate

Prefiero esto al método javascript window.open porque si el enlace está roto, el método iframe simplemente no hace nada en lugar de redirigir a una página en blanco que dice que el archivo no se pudo abrir.

window.open(downloadUrl, 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0');
window.focus();
alockwood05
fuente
6

Uso de la API de archivo de URL de objeto de blob HTML5 :

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
*/
var saveBlobAsFile = function(fileName,fileContents) {
    if(typeof(Blob)!='undefined') { // using Blob
        var textFileAsBlob = new Blob([fileContents], { type: 'text/plain' });
        var downloadLink = document.createElement("a");
        downloadLink.download = fileName;
        if (window.webkitURL != null) {
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else {
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    } else {
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.onclick = document.body.removeChild(event.target);
        pp.click();
    }
}//saveBlobAsFile

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
 */
var saveBlobAsFile = function(fileName, fileContents) {
  if (typeof(Blob) != 'undefined') { // using Blob
    var textFileAsBlob = new Blob([fileContents], {
      type: 'text/plain'
    });
    var downloadLink = document.createElement("a");
    downloadLink.download = fileName;
    if (window.webkitURL != null) {
      downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    } else {
      downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
      downloadLink.onclick = document.body.removeChild(event.target);
      downloadLink.style.display = "none";
      document.body.appendChild(downloadLink);
    }
    downloadLink.click();
  } else {
    var pp = document.createElement('a');
    pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
    pp.setAttribute('download', fileName);
    pp.onclick = document.body.removeChild(event.target);
    pp.click();
  }
} //saveBlobAsFile

var jsonObject = {
  "name": "John",
  "age": 31,
  "city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";

saveBlobAsFile(fileName, fileContents)

Loretoparisi
fuente
2
¡¡Siento que esta es la mejor manera de hacerlo !!
Kushal MK
1
También es una buena práctica llamar URL.revokeObjectURL(url)cuando ya no se necesita el archivo para liberar memoria
SleepWalker
5

La modificación de la ubicación de la ventana puede causar algún problema, especialmente cuando tiene una conexión persistente como websocket. Así que siempre recurro a la vieja solución de iframe.

HTML

<input type="button" onclick="downloadButtonClicked()" value="Download"/>
...
...
...
<iframe style="display:none;" name="hiddenIframe" id="hiddenIframe"></iframe>

Javascript

function downloadButtonClicked() {
    // Simulate a link click
    var url = 'your_download_url_here';
    var elem = document.createElement('a');
    elem.href = url;
    elem.target = 'hiddenIframe';
    elem.click();
}
Bnrdo
fuente
5

Si el enlace es a una URL de archivo válida, simplemente la asignación de window.location.href funcionará.

Sin embargo, a veces el enlace no es válido y se requiere un iFrame.

Haz tu event.preventDefault normal para evitar que la ventana se abra, y si estás usando jQuery, esto funcionará:

$('<iframe>').attr('src', downloadThing.attr('href')).appendTo('body').on("load", function() {
   $(this).remove();
});
TaylorMac
fuente
2

Después de horas de intentarlo, nació la función :) Tuve un escenario en el que tenía que mostrar el cargador a tiempo mientras el archivo se preparaba para descargar:

Trabajando en Chrome, Safari y Firefox

function ajaxDownload(url, filename = 'file', method = 'get', data = {}, callbackSuccess = () => {}, callbackFail = () => {}) {
    $.ajax({
        url: url,
        method: 'GET',
        xhrFields: {
            responseType: 'blob'
        },
        success: function (data) {
            // create link element
            let a = document.createElement('a'), 
                url = window.URL.createObjectURL(data);

            // initialize 
            a.href = url;
            a.download = filename;

            // append element to the body, 
            // a must, due to Firefox
            document.body.appendChild(a);

            // trigger download
            a.click();

            // delay a bit deletion of the element
            setTimeout(function(){
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);
            }, 100);

            // invoke callback if any 
            callbackSuccess(data);
        },
        error: function (err) {
            // invoke fail callback if any
            callbackFail(err)
        }
    });
М.Б.
fuente
0

Qué tal si:

<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">

De esta manera funciona en todos los navegadores (creo) y te permite poner un mensaje como: "Si la descarga no comienza en cinco segundos, haz clic aquí".

Si necesita que sea con javascript .. bueno ...

document.write('<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">');

Saludos


fuente
0

Un iframe pequeño / oculto puede funcionar para este propósito.

De esa manera, no tendrá que preocuparse por cerrar la ventana emergente.

Simón
fuente