Tengo una acción Struts2 en el lado del servidor para la descarga de archivos.
<action name="download" class="com.xxx.DownAction">
<result name="success" type="stream">
<param name="contentType">text/plain</param>
<param name="inputName">imageStream</param>
<param name="contentDisposition">attachment;filename={fileName}</param>
<param name="bufferSize">1024</param>
</result>
</action>
Sin embargo, cuando llamo a la acción usando jQuery:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
En Firebug veo que los datos se recuperan con la secuencia binaria . Me pregunto cómo abrir la ventana de descarga de archivos con la que el usuario puede guardar el archivo localmente.
Respuestas:
Actualización de navegadores modernos 2019
Este es el enfoque que ahora recomendaría con algunas advertencias:
Enfoque basado en jQuery / iframe / cookie original de 2012
Bluish tiene toda la razón sobre esto, no puede hacerlo a través de Ajax porque JavaScript no puede guardar archivos directamente en la computadora de un usuario (por motivos de seguridad). Desafortunadamente, señalar la URL de la ventana principal en la descarga de su archivo significa que tiene poco control sobre la experiencia del usuario cuando se produce una descarga de archivo.
He creado jQuery Descarga de archivos que permite una "Ajax como" experiencia con las descargas de archivos completos con onSuccess y onFailure devoluciones de llamada para proporcionar una mejor experiencia de usuario. Echa un vistazo a mi blog sobre el problema común que resuelve el complemento y algunas formas de usarlo y también un demostración de jQuery File Download en acción . Aquí esta la fuente
Aquí hay una demostración de caso de uso simple usando la fuente del complemento con promesas. La página de demostración incluye muchos otros ejemplos de 'mejor UX'.
Dependiendo de los navegadores que necesite admitir, puede usar https://github.com/eligrey/FileSaver.js/ que permite un control más explícito que el método IFRAME que utiliza la descarga de archivos jQuery.
fuente
Nadie publicó esta solución de @ Pekka ... así que la publicaré. Puede ayudar a alguien.
No necesita hacer esto a través de Ajax. Solo usa
fuente
window.open(<url>, '_blank');
para asegurarse de que la descarga no reemplace el contenido actual de su navegador (independientemente del encabezado Content-Disposition).POST
solicitud.Puedes con HTML5
NB: los datos de archivo devueltos DEBEN estar codificados en base64 porque no puede codificar JSON datos binarios
En mi
AJAX
respuesta, tengo una estructura de datos que se ve así:Eso significa que puedo hacer lo siguiente para guardar un archivo a través de AJAX
La función base64ToBlob se tomó de aquí y debe usarse de conformidad con esta función
Esto es bueno si su servidor está volcando datos de archivos para guardar. Sin embargo, aún no he resuelto cómo se implementaría un respaldo HTML4
fuente
a.click()
no parece funcionar en Firefox ... ¿Alguna idea?a
dom para que este código funcione y / o eliminar larevokeObjectURL
parte:document.body.appendChild(a)
var bytechars = atob(base64)
arroja un errorJavaScript runtime error: InvalidCharacterError
. Estoy usando Chrome Versión 75.0.3770.142 pero no sé, qué está mal aquí.1. Marco independiente: archivo de descarga de servlet como archivo adjunto
2. Struts2 Framework: Acción descargando archivo como archivo adjunto
Sería mejor usar la
<s:a>
etiqueta apuntando con OGNL a una URL creada con la<s:url>
etiqueta:En los casos anteriores, debe escribir el encabezado Content-Disposition en la respuesta , especificando que el archivo debe ser descargado (
attachment
) y no abierto por el navegador (inline
). También debe especificar el Tipo de contenido , y es posible que desee agregar el nombre y la longitud del archivo (para ayudar al navegador a dibujar una barra de progreso realista).Por ejemplo, al descargar un ZIP:
Con Struts2 (a menos que esté utilizando la Acción como un Servlet, un truco para la transmisión directa , por ejemplo), no necesita escribir directamente nada en la respuesta; simplemente usando el tipo de resultado Stream y configurándolo en struts.xml funcionará: EJEMPLO
3. Framework agnóstico (/ Struts2 framework): Servlet (/ Action) abriendo el archivo dentro del navegador
Si desea abrir el archivo dentro del navegador, en lugar de descargarlo, la disposición de contenido debe establecerse en línea , pero el destino no puede ser la ubicación actual de la ventana; debe orientar una nueva ventana creada por javascript, una
<iframe>
en la página o una nueva ventana creada sobre la marcha con el "discutido" target = "_ blank":fuente
too long url
error.La manera simple de hacer que el navegador descargue un archivo es hacer la solicitud de esta manera:
Esto abre la ventana emergente de descarga del navegador.
fuente
He creado poca función como solución alternativa (inspirada en el complemento @ JohnCulviner):
Demostración con evento de clic:
fuente
Enfrenté el mismo problema y lo resolví con éxito. Mi caso de uso es este.
" Publique datos JSON en el servidor y reciba un archivo de Excel. Ese archivo de Excel es creado por el servidor y devuelto como respuesta al cliente. Descargue esa respuesta como un archivo con nombre personalizado en el navegador "
El fragmento anterior solo hace lo siguiente
Aquí necesitamos establecer cuidadosamente algunas cosas en el lado del servidor. Configuré algunos encabezados en Python Django HttpResponse. Debe configurarlos en consecuencia si usa otros lenguajes de programación.
Desde que descargo xls (excel) aquí, ajusté contentType al anterior. Debe configurarlo de acuerdo con su tipo de archivo. Puede usar esta técnica para descargar cualquier tipo de archivo.
fuente
HTMLAnchorElement.download
, estoy pensando en combinarlo con el método patentado msSaveOrOpenBlob .Ok, basado en el código de ndpu heres una versión mejorada (creo) de ajax_download; -
Use esto así; -
Los parámetros se envían como parámetros posteriores apropiados como si vinieran de una entrada en lugar de una cadena codificada json como en el ejemplo anterior.
PRECAUCIÓN: Tenga cuidado con el potencial de inyección variable en esas formas. Puede haber una forma más segura de codificar esas variables. Alternativamente, contempla escapar de ellos.
fuente
Uncaught SecurityError: Blocked a frame with origin "http://foo.bar.com" from accessing a frame with origin "null". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "data". Protocols must match.
@ResourceMapping() public void downloadFile(final ResourceRequest request, final ResourceResponse response, @ModelAttribute("downForm") FormModel model)
pero no funciona ..Esto es lo que hice, javascript puro y html. No lo probé, pero esto debería funcionar en todos los navegadores.
fuente
fuente
download
atributo, por lo que su archivo terminará teniendo el nombre "Desconocido"En Rails, lo hago de esta manera:
El truco es la parte window.location . El método del controlador se ve así:
fuente
Use
window.open
https://developer.mozilla.org/en-US/docs/Web/API/Window/openPor ejemplo, puede poner esta línea de código en un controlador de clics:
Se abrirá una nueva pestaña (debido al nombre de la ventana '_blank') y esa pestaña abrirá la URL.
Su código del lado del servidor también debería tener algo como esto:
Y de esa manera, el navegador debe solicitar al usuario que guarde el archivo en el disco, en lugar de solo mostrarle el archivo. También cerrará automáticamente la pestaña que acaba de abrir.
fuente
Intento descargar un archivo CSV y luego hacer algo después de que la descarga haya finalizado. Entonces necesito implementar una
callback
función apropiada .Usar
window.location="..."
no es una buena idea porque no puedo operar el programa después de terminar la descarga. Algo como esto, cambia el encabezado para que no sea una buena idea.fetch
es una buena alternativa, sin embargo, no puede soportar IE 11 . Ywindow.URL.createObjectURL
no puede soportar IE 11. Puedes referir esto .Este es mi código, es similar al código de Shahrukh Alam. Pero debe tener cuidado de que
window.URL.createObjectURL
tal vez cree pérdidas de memoria. Puedes referir esto . Cuando llegue la respuesta, los datos se almacenarán en la memoria del navegador. Entonces, antes de hacer clic en ela
enlace, el archivo se ha descargado. Significa que puede hacer cualquier cosa después de la descarga.fuente
Cómo DESCARGAR un archivo después de recibirlo por AJAX
Es conveniente cuando el archivo se crea durante mucho tiempo y necesita mostrar PRELOADER
Ejemplo al enviar un formulario web:
Opcional funcional se comenta para simplificar el ejemplo.
No es necesario crear archivos temporales en el servidor.
En jQuery v2.2.4 OK. Habrá un error en la versión anterior:
fuente
filename.match(/filename=(.*)/)[1]
(sin las comillas dobles o el signo de interrogación) - regex101.com/r/2AsD4y/2 . Sin embargo, su solución fue la única solución que funcionó después de buscar mucho.Agregar algunas cosas más a la respuesta anterior para descargar un archivo
A continuación se muestra un código java spring que genera una matriz de bytes
Ahora en código javascript usando FileSaver.js, puede descargar un archivo con el siguiente código
Lo anterior descargará el archivo
fuente
Ok, aquí está el código de trabajo al usar MVC y estás obteniendo tu archivo de un controlador
supongamos que tiene su conjunto de bytes declarar y llenar, lo único que debe hacer es usar la función de archivo (usando System.Web.Mvc)
y luego, en el mismo controlador, agregue estas 2 funciones
y luego podrá llamar a su controlador para descargar y obtener la devolución de llamada de "éxito" o "falla"
fuente
Encontré una solución que, si bien en realidad no está usando ajax, le permite usar una llamada de JavaScript para solicitar la descarga y luego recibir una devolución de llamada cuando la descarga realmente comienza. Esto me pareció útil si el enlace ejecuta un script del lado del servidor que toma un poco de tiempo para componer el archivo antes de enviarlo. para que pueda alertarlos de que se está procesando, y luego, cuando finalmente envíe el archivo, elimine esa notificación de procesamiento. Por eso, para empezar, quería intentar cargar el archivo a través de ajax para poder tener un evento cuando se solicita el archivo y otro cuando realmente comienza a descargarse.
el js en la portada
el iframe
entonces el otro archivo:
Creo que hay una manera de leer los datos usando js para que no se necesite php. pero no lo sé de la mano y el servidor que estoy usando es compatible con php, así que esto funciona para mí. pensé en compartirlo en caso de que ayude a alguien.
fuente
Si desea utilizar la descarga de archivos jQuery, tenga en cuenta esto para IE. Necesita restablecer la respuesta o no se descargará
Su acción puede implementar
ServletResponseAware
para accedergetServletResponse()
fuente
Es cierto que no puede hacerlo a través de la llamada Ajax.
Sin embargo, hay una solución.
Pasos:
Si está utilizando form.submit () para descargar el archivo, lo que puede hacer es:
Esto es útil en caso de que desee decidir si el archivo debe descargarse o no después de crear form.submit (), por ejemplo: puede haber un caso en el que en form.submit (), se produzca una excepción en el lado del servidor y, en su lugar de bloqueo, es posible que deba mostrar un mensaje personalizado en el lado del cliente, en tal caso, esta implementación podría ayudar.
fuente
Hay otra solución para descargar una página web en ajax. Pero me refiero a una página que primero debe procesarse y luego descargarse.
Primero debe separar el procesamiento de la página de la descarga de resultados.
1) Solo los cálculos de la página se realizan en la llamada ajax.
Espero que esta solución pueda ser útil para muchos, como lo fue para mí.
fuente
fuente
Eso funciona muy bien en cualquier navegador (estoy usando asp.net core)
fuente
Luché con este problema durante mucho tiempo. Finalmente, una elegante biblioteca externa sugerida aquí me ayudó.
fuente