2008-09-13 16 views
12

En un sitio web basado en PHP, deseo enviar a los usuarios un paquete de descarga después de haber completado un breve formulario. La descarga iniciada por el sitio debe ser similar a sitios como download.com, que dicen "la descarga comenzará en un momento".¿La mejor manera de iniciar una descarga?

Un par de enfoques posibles que sé de, y la compatibilidad del navegador (basado en una prueba rápida):

1) Haz una window.open apuntando al nuevo archivo.

- FireFox 3 blocks this. 
- IE6 blocks this. 
- IE7 blocks this. 

2) Crear un iframe que apunta al nuevo archivo.

- FireFox 3 seems to think this is OK. (Maybe it's because I already accepted it once?) 
- IE6 blocks this. 
- IE7 blocks this. 

How can I do this so that at least these three browsers will not object? 

Bono: ¿existe un método que no requiere declaraciones navegador condicional?

(. Creo que download.com emplea ambos métodos en forma condicional, pero no puedo obtener ya sea uno a trabajar)

Respuestas y Aclaraciones:

Q: "Why not point the current window to the file?" 
A: That might work, but in this particular case, I want to show them some other content while their download starts - for example, "would you like to donate to this project?" 

ACTUALIZACIÓN: Tengo abandonado este enfoque. Vea mi respuesta a continuación por razones.

Respuesta

16

También puede hacer una meta actualización, que la mayoría de los navegadores son compatibles. Download.com coloca uno en una etiqueta noscript.

<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip"/> 
+2

I * hate * those. Tengo que esperar unos segundos para descargar, que a veces toma 1 segundo. Mi navegador guarda las sesiones de navegación, lo que significa que los archivos comienzan a aparecer de ninguna manera cuando reinicio el navegador. No puedo copiar el enlace o tengo que buscar "haga clic aquí si ..." en la página y detener la descarga automática. – Kornel

+0

De acuerdo, pero fue lo que pidió inicialmente. – Soldarnal

0

¿Qué le parece cambiar la ubicación para que apunte al nuevo archivo? (Por ejemplo, cambiando window.location)

5

por lo general sólo tienen un script PHP que genera el archivo directamente en el navegador con la adecuada Content-Type

if(file_exists($filename)) { 
    header("Pragma: public"); 
    header("Expires: 0"); 
    header("Cache-Control: must-revalidate, pre-check=0"); 
    header("Cache-Control: private", false); 
    header("Content-Type: " . $content-type); 
    header("Content-Disposition: attachment; filename=\"" . basename($filename) . "\";"); 
    header("Content-Transfer-Encoding: binary"); 
    header("Content-Length: " . filesize($filename)); 

    readfile("$filename"); 
}else{ 
    print "ERROR: the file " . basename($filename) . " could not be downloaded because it did not exist."; 
} 

La única desventaja es que, ya que establece la Encabezado HTTP, debe ser llamado antes de tener cualquier otro resultado.

Pero puede tener un enlace a la página de descarga de PHP y hará que el navegador muestre un cuadro de descarga sin estropear el contenido de la página actual.

+0

Marca: esto debe estar por encima de mi cabeza; No entiendo nada sobre las cabeceras. ¿Este método te permite acceder a otra página mientras se inicia la descarga? –

+0

Básicamente lo que estás haciendo es leer los contenidos binarios del archivo y enviar esos datos binarios al navegador en lugar de HTML. El tipo de contenido simplemente le dice al navegador qué tipo de archivo es. Intente crear una página simple que sea solo mi fragmento de código y conecte un nombre de archivo y un tipo de contenido. –

+0

Algunos tipos de contenido útil saber son application/zip plicación/pdf application/octet-stream application/acceso aplicación/pdf application/vnd.ms-excel imagen application/vnd.ms-powerpoint /gif imagen/png imagen/jpg –

0

Siempre he hecho un iframe que apunta al archivo.

<iframe src="/download.exe" frameborder="0" height="0" width="0"><a href="/download.exe">Click here to download.</a></iframe> 
0

En cuanto a no señalar la ventana actual a la descarga. Según mi experiencia, todavía puede mostrar su página "por favor done", ya que las descargas (siempre que envíen los encabezados correctos) no actualizan la ventana del navegador. Lo hago para las exportaciones de csv en uno de mis sitios, y en lo que respecta al usuario, solo aparece una ventana de archivo seguro. Así que recomendaría un simple meta-redirect como Soldarnal mostró.

0

Sólo para resumir, que tiene 2 objetivos:

  1. proceso de puesta en descarga
  2. programa de usuario a una página con un donar opciones

Para lograr esto haría lo siguiente:

Cuando su usuario envía el formulario, obtiene la página resultante con opciones de donación y un texto que dice que su descarga comenzará en 5 segundos. Y en la sección de cabecera de esta página se pone el código META como dijo Soldarnal:? < meta http-equiv = "refresh" content = "5; url =/= download.php doc 123.zip >

y eso es todo.

1

Un problema es que es posible que surjan problemas con IE (versión 6 en particular) si los encabezados no están preparados "correctamente".

Asegúrese de configurar el derecho Content-Type, sino también en cuenta establecer las opciones de caché para IE (al menos) en permite el almacenamiento en memoria caché. Si el archivo es uno que el usuario puede abrir en lugar de guardar (por ejemplo, un documento de MS Word) v Las ersiones de IE necesitan almacenar en caché el archivo, ya que entregan la solicitud "abierta" a la aplicación correspondiente, apuntando al archivo que se descargó en la memoria caché.

También hay un problema relacionado, si la memoria caché del usuario IE6 está lleno, no va a guardar correctamente el archivo (por lo tanto cuando la aplicación aplicable pone la mano fuera para abrirlo, se quejan de que el archivo está dañado.

también es posible que desee a su vez la existencia de acciones gzip en las descargas también (para IE)

IE6/IE7 ambos tienen problemas con descargas de gran tamaño (por ejemplo, 4.x Conciertos ...) no es un escenario probable, ya que doesn IE incluso tiene un administrador de descargas, pero hay que tener en cuenta.

Por último, IE6 a veces no maneja muy bien una descarga "push" si se inició dentro de un iframe anidado. No estoy exactamente seguro de qué desencadena el problema, pero me resulta más fácil con IE6 evitar este escenario.

15

Actualización: he decidido abandonar este enfoque, y en su lugar solo presentar al usuario un enlace al archivo real. Mi razonamiento es el siguiente:

Mis intentos iniciales de una descarga iniciada por el servidor fueron bloqueados por el navegador. Eso me hizo pensar: "el navegador es correcto. ¿Cómo sabe que esta es una descarga legítima? debe bloquear una descarga que obviamente no inicia el usuario".

Cualquier método que pueda usar para una descarga iniciada por el servidor podría ser también utilizado por alguien que quiera enviar malware. Por lo tanto, las descargas solo deben realizarse cuando el usuario solicita específicamente el archivo haciendo clic en un enlace.

Puede estar en desacuerdo, y si aún desea iniciar una descarga, con suerte este hilo lo ayudará a hacerlo.

1

Hoi!

@Nathan: Decidí hacer exactamente eso: Tener mi "archivo get".php" carga en todo lo necesario y luego hacer un

header("Location: ./$path/$filename"); 

dejar que el propio navegador y ver directamente lo que piensa es correcto hacer con el archivo. Esto incluso funciona bien en Opera conmigo.

Pero esto será un problema en ambientes, donde no se permite el acceso directo a los archivos, en ese caso, tendrá que encontrar una manera diferente! (Gracias Discordia mis archivos son archivos PDF públicas!)

saludos, Basty

0
<a href="normaldownload.zip" onclick="use_dhtml_or_ajax_to_display_page()"> 

La página actual no se ve afectada si se guarda la descarga. Solo asegúrese de que la descarga no se abra en la misma ventana (tipo MIME correcto o Content-Disposition) y podrá mostrar cualquier cosa.

See more complete answer

0

Puede utilizar Javascript/jQuery para iniciar la descarga. Aquí hay un ejemplo: puede deshacerse de la solicitud de Ajax y simplemente usar el bloque setTimeout().

$("btnDownloadCSV").on('click', function() { 
    $.ajax({ 
     url: "php_backend/get_download_url", 
     type: 'post', 
     contentType: "application/x-www-form-urlencoded", 
     data: {somedata: "somedata"}, 
     success: function(data) { 
      // If iFrame already exists, remove it. 
      if($("[id^='iframeTempCSV_"]).length) { 
       $("[id^='iframeTempCSV_"]).remove(); 
      } 
      setTimeout(function() { 
       // If I'm creating an iframe with the same id, it will permit download only the first time. 
       // So randHashId appended to ID to trick the browser. 
       var randHashId = Math.random().toString(36).substr(2); 
       // Create a fresh iFrame for auto-downloading CSV 
       $('<iframe id="iframeTempCSV_'+randHashId+'" style="display:none;" src="'+data.filepath+'"></iframe>').appendTo('body'); 
      }, 1000); 
     }, 
     error: function(xhr, textStatus, errorThrown) { 
      console.error("Error downloading..."); 
     } 
    }); 
}); 
Cuestiones relacionadas