javascript - forzar - descargar archivo usando una solicitud ajax
forzar descarga javascript (7)
En realidad, no necesitas ajax en absoluto para esto. Si simplemente configura "download.php" como href en el botón, o si no es un enlace, use:
window.location = ''download.php'';
El navegador debe reconocer la descarga binaria y no cargar la página real, sino solo servir el archivo como descarga.
Deseo enviar una "solicitud de descarga de Ajax" cuando hago clic en un botón, así que lo intenté de esta manera:
javascript:
var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();
download.php:
<?
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= file.txt");
header("Content-Transfer-Encoding: binary");
readfile("file.txt");
?>
pero no funciona como se esperaba, ¿cómo puedo hacer? Gracias de antemano
Es posible. Puede hacer que la descarga se inicie desde dentro de una función ajax, por ejemplo, justo después de que se haya creado el archivo .csv.
Tengo una función ajax que exporta una base de datos de contactos a un archivo .csv, y justo después de que termine, inicia automáticamente la descarga del archivo .csv. Entonces, después de obtener el texto de respuesta y todo está bien, redirijo el navegador de esta manera:
window.location="download.php?filename=export.csv";
Mi archivo download.php se ve así:
<?php
$file = $_GET[''filename''];
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=".$file."");
header("Content-Transfer-Encoding: binary");
header("Content-Type: binary/octet-stream");
readfile($file);
?>
No hay actualización de página alguna y el archivo comienza a descargarse automáticamente.
NOTA - Probado en los siguientes navegadores:
Chrome v37.0.2062.120
Firefox v32.0.1
Opera v12.17
Internet Explorer v11
La decodificación de un nombre de archivo desde el encabezado es un poco más compleja ...
var filename = "default.pdf";
var disposition = req.getResponseHeader(''Content-Disposition'');
if (disposition && disposition.indexOf(''attachment'') !== -1)
{
var filenameRegex = /filename[^;=/n]*=(([''"]).*?/2|[^;/n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1])
filename = matches[1].replace(/[''"]/g, '''');
}
Para que el navegador descargue un archivo, debe realizar una solicitud como esta:
function downloadFile(urlToSend) {
var req = new XMLHttpRequest();
req.open("GET", urlToSend, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
var link=document.createElement(''a'');
link.href=window.URL.createObjectURL(blob);
link.download=fileName;
link.click();
};
req.send();
}
Prefiero Location.assign ()
Solución de navegador cruzado, probado en Chrome, Firefox, Edge, IE11.
En el DOM, agrega una etiqueta de enlace oculto:
<a id="target" style="display: none"></a>
Entonces:
var req = new XMLHttpRequest();
req.open("GET", downloadUrl, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var fileName = null;
var contentType = req.getResponseHeader("content-type");
// IE/EDGE seems not returning some response header
if (req.getResponseHeader("content-disposition")) {
var contentDisposition = req.getResponseHeader("content-disposition");
fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
} else {
fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
}
if (window.navigator.msSaveOrOpenBlob) {
// Internet Explorer
window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
} else {
var el = document.getElementById("target");
el.href = window.URL.createObjectURL(blob);
el.download = fileName;
el.click();
}
};
req.send();
Actualización 27 de abril de 2015
Arriba y llegando a la escena HTML5 es el atributo de descarga . Es supported con Firefox y Chrome, y pronto llegará a IE11. Dependiendo de sus necesidades, podría usarlo en lugar de una solicitud AJAX (o usando window.location
) siempre que el archivo que desea descargar esté en el mismo origen que su sitio.
Siempre puede hacer que la solicitud / window.location
AJAX sea una alternativa mediante el uso de JavaScript para probar si la download
es compatible y, de lo contrario, cambiarla para llamar a window.location
.
Respuesta original
No puede tener una solicitud AJAX para abrir la solicitud de descarga, ya que físicamente tiene que navegar hasta el archivo para solicitar la descarga. En cambio, puede usar una función de éxito para navegar a download.php. Esto abrirá el mensaje de descarga pero no cambiará la página actual.
$.ajax({
url: ''download.php'',
type: ''POST'',
success: function() {
window.location = ''download.php'';
}
});
Aunque esto responde a la pregunta, es mejor usar window.location
y evitar la solicitud AJAX por completo.