2008-09-29 9 views
40

Mi aplicación genera archivos PDF para el consumo del usuario. El encabezado http "Contenido-Disposición" se establece como se menciona here. Esto se establece en "inline; filename = foo.pdf", que debería ser suficiente para que Acrobat proporcione "foo.pdf" como nombre de archivo al guardar el pdf."nombre" web pdf para una mejor configuración predeterminada de guardar nombre de archivo en Acrobat?

Sin embargo, al hacer clic en el botón "Guardar" en el Acrobat incrustado en el navegador, el nombre predeterminado para guardar no es ese nombre de archivo sino que la URL con barras cambia a guiones bajos. Enorme y feo. ¿Hay alguna forma de afectar este nombre de archivo predeterminado en Adobe?

HAY una cadena de consulta en las URL, y esto no es negociable. Esto puede ser significativo, pero agregar un "& foo =/title.pdf" al final de la URL no afecta el nombre de archivo predeterminado.

Actualización 2: He intentado tanto

content-disposition inline; filename=foo.pdf 
Content-Type   application/pdf; filename=foo.pdf 

y

content-disposition inline; filename=foo.pdf 
Content-Type   application/pdf; name=foo.pdf 

(como se verifica a través de Firebug) Por desgracia, ni trabajado.

Un ejemplo de URL es

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true

que se traduce en un valor predeterminado de Acrobat guardar como nombre de archivo del

http___localhost_bar_sessions_958d8a22-0_views_1493881172_export_format=application_pdf&no-attachment=true.pdf

Actualización 3: Julian Reschke aporta una visión real y el rigor a este caso. Por favor, vote su respuesta. Esto parece estar roto en FF (https://bugzilla.mozilla.org/show_bug.cgi?id=433613) e IE pero funciona en Opera, Safari y Chrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf

Respuesta

10

Parte del problema es que el RFC 2183 relevante realmente no dice qué hacer con un tipo de disposición de "en línea" y un nombre de archivo.

Además, hasta donde puedo decir, el único UA que realmente usa el nombre de archivo para type = inline es Firefox (ver test case).

Por último, no es obvio que la API de complemento realmente hace que la información esté disponible (tal vez alguien familiarizado con la API pueda dar más detalles).

Dicho esto, he enviado un puntero a esta pregunta a una persona de Adobe; tal vez las personas correctas echarán un vistazo.

Relacionados: vea el intento de aclarar Contenido-Disposición en HTTP en draft-reschke-rfc2183-in-http - este es un trabajo en progreso, comentarios apreciados.

Actualización: He agregado un test case, lo que parece indicar que el complemento de Acrobat Reader no usa los encabezados de respuesta (en Firefox), aunque la API del complemento les proporciona acceso.

+1

¿Hay alguna solución/solución a este problema? –

+0

Acabo de intentar agregar contenido-disposición en línea; filename = foo.pdf y parece funcionar en Chrome, al menos. – gorantq

0

Siempre puede tener dos enlaces. Uno que abre el documento dentro del navegador y otro para descargarlo (usando un tipo de contenido incorrecto). Esto es lo que hace Gmail.

+0

Lo sentimos, pero creo que esto sería peor (en cuanto a la experiencia del usuario) que no hacer nada. Cambiar el nombre de un archivo no es un gran problema, solo uno molesto. –

+0

Bastante justo. Gmail lo hace con imágenes, y me gusta bastante. Buena suerte de todos modos :-) –

7

Establezca el nombre de archivo en ContentType también. Esto deberia resolver el problema.

context.Response.ContentType = "application/pdf; name=" + fileName; 
// the usual stuff 
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName); 

Después de establecer encabezado content-disposition, también añade una cabecera Content-Length, a continuación, utilizar BinaryWrite para transmitir los PDF.

context.Response.AddHeader("Content-Length", fileBytes.Length.ToString()); 
context.Response.BinaryWrite(fileBytes); 
+1

Él ya lo hizo. Acrobat Reader lo ignora, o eso parece. –

+1

La sugerencia es establecer ContentType = "application/pdf; name = foo.pdf" que no dice que lo intentó. – Vivek

+0

Tenía grandes esperanzas, pero esto no parece afectar a Acrobat Reader 8.0 en IE o FF. Pregunta actualizada –

1

En lugar de unión puede probar en línea:

Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf"); 

utilicé en línea en una aplicación web anterior que generó Crystal Reports de salida en formato PDF y se envía de que en el navegador para el usuario.

9

Como usted, traté y traté de hacer que esto funcione. Finalmente abandoné esta idea y simplemente opté por una solución alternativa.

Estoy usando ASP.NET MVC Framework, así que modifiqué mis rutas para ese controlador/acción para asegurarme de que el archivo PDF servido sea la última parte de la porción de ubicación del URI (antes de la cadena de consulta) y pasa todo lo demás en la cadena de consulta.

Ej:

Antiguo URI:

http://server/app/report/showpdf?param1=foo&param2=bar&filename=myreport.pdf

Nueva URI:

http://server/app/report/showpdf/myreport.pdf?param1=foo&param2=bar

La cabecera resultante es exactamente igual a lo que usted ha descrito (tipo de contenido es application/pdf, la disposición está en línea, el nombre de archivo es inútilmente parte del encabezado). Acrobat lo muestra en la ventana del navegador (no se guarda como diálogo) y el nombre de archivo que se completa automáticamente si un usuario hace clic en el botón Guardar de Acrobat es el nombre de archivo del informe.

Algunas consideraciones:

Para que los nombres de archivo para buscar decente, que no debería tener ningún caracteres de escape (es decir, sin espacios, etc) ... lo cual está limitando un poco. Mis nombres de archivo se generan automáticamente en este caso, y antes tenían espacios en ellos, que aparecían como '% 20 en el nombre del archivo de diálogo de guardar resultante. Acabo de reemplazar los espacios con guiones bajos, y funcionó.

Esta es de ninguna manera la mejor solución, pero funciona. También significa que debe tener el nombre de archivo disponible para que forme parte del URI original, lo que podría interferir con el flujo de trabajo de su programa. Si actualmente se está generando o recuperando de una base de datos durante la llamada del servidor que genera el PDF, es posible que deba mover el código que genera el nombre de archivo a javascript como parte de un envío de formulario o si proviene de una base de datos hacerlo un llamada rápida ajax para obtener el nombre de archivo al construir la URL que da como resultado el PDF en línea.

Si toma el nombre de archivo de una entrada de usuario en un formulario, entonces debe validarse para que no contenga caracteres escapados, lo que molestará a los usuarios.

Espero que ayude.

+0

Excelente idea. :) –

0

Fui redireccionado aquí porque tengo el mismo problema. También probé la solución provisional de Troy Howard, pero parece que no funciona.

El enfoque que hice en este caso es NO usar más el objeto de respuesta para escribir el archivo sobre la marcha. Como el PDF ya existe en el servidor, lo que hice fue redireccionar mi página apuntando a ese archivo PDF. Funciona genial.

http://forums.asp.net/t/143631.aspx

espero que mi vaga explicación que dio una idea.

-1

Prueba de esto, si el ejecutable es "get.cgi"

http://server,org/get.cgi/filename.pdf?file=filename.pdf

Sí, es completamente loco. No hay un archivo llamado "nombredearchivo.pdf" en el servidor, hay un directorio bajo el ejecutable get.cgi.

Pero parece que funciona. El servidor ignora el filename.pdf y el lector de pdf ignora el "get.cgi"

Dan

+0

¿Eso parece depender de un error en su servidor web? Eso debería 404 según la especificación: ¿Apache se comporta de esta manera? –

+0

Eso no es * completamente * insano, ni debería necesariamente dar como resultado un 404. Las rutas adicionales que siguen a un ejecutable CGI son válidas y deberían dar como resultado que se establezca la variable CGI PATH_INFO. Dicho esto, no creo que sea la forma más limpia de resolver este problema. – asmecher

1

Creo que esto ya se ha mencionado en uno u otro sabor, pero voy a tratar y el estado en mi propia palabras.

En lugar de esto:

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true 

utilizo este:

/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf?GeneratePDF=1 

En lugar de tener proceso de "exportar" la solicitud, cuando llega una petición, miro en la dirección URL de GeneratePDF = 1. Si se encuentra, ejecuto el código que se estaba ejecutando en "exportar" en lugar de permitir que mi sistema intente buscar y publicar un PDF en la ubicación /bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf. Si GeneratePDF no se encuentra en la URL, simplemente transmito el archivo solicitado. (Tenga en cuenta que no puedo simplemente redireccionar al archivo solicitado, o de lo contrario terminaría en un bucle infinito)

2

Si utiliza asp.net, puede controlar el nombre del archivo pdf a través del nombre del archivo de página (url). Como escribieron otros usuarios, Acrobat está un poco s ... cuando elige el nombre del archivo pdf cuando presiona el botón "guardar": toma el nombre de la página, elimina la extensión y agrega ".pdf". Así /foo/bar/GetMyPdf.aspx da GetMyPdf.pdf.

La única solución que encontré es la gestión de los nombres de página "dinámicas" a través de un controlador de asp.net:

  • crear una clase que implementa IHttpHandler
  • mapa un controlador en la web.config limitada a la clase

Mapping1: todas las páginas tienen una raíz común (MyDocument_):

<httpHandlers> 
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/> 

Mapping2: nombre de archivo completamente libre (necesita una carpeta en la ruta):

<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/> 

Algunos consejos aquí (el pdf se crea dinámicamente usando iTextSharp):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html

0

La forma en que resolvió esto (con PHP) es la siguiente:

Supongamos que su URL es SomeScript.php?id=ID&data=DATA y el archivo que desea usar es TEST.pdf.

Cambie la URL a SomeScript.php/id/ID/data/DATA/EXT/TEST.pdf.

Es importante que el último parámetro sea el nombre de archivo que desea que Adobe use (el 'EXT' puede ser sobre cualquier cosa). Asegúrese de que no haya caracteres especiales en la cadena anterior, por cierto.

Ahora, en la parte superior de SomeScript.php, añadir:

$_REQUEST = MakeFriendlyURI($_SERVER['PHP\_SELF'], $_SERVER['SCRIPT_FILENAME']); 

A continuación, añadir esta función para SomeScript.php (o su biblioteca de funciones):

function MakeFriendlyURI($URI, $ScriptName) { 

/* Need to remove everything up to the script name */ 
$MyName = '/^.*'.preg_quote(basename($ScriptName)."/", '/').'/'; 
$Str = preg_replace($MyName,'',$URI); 
$RequestArray = array(); 

/* Breaks down like this 
     0  1  2  3  4  5 
    PARAM1/VAL1/PARAM2/VAL2/PARAM3/VAL3 
*/ 

$tmp = explode('/',$Str); 
/* Ok so build an associative array with Key->value 
    This way it can be returned back to $_REQUEST or $_GET 
*/ 
for ($i=0;$i < count($tmp); $i = $i+2){ 
    $RequestArray[$tmp[$i]] = $tmp[$i+1]; 
} 
return $RequestArray;  
}//EO MakeFriendlyURI 

ahora $_REQUEST (o $_GET si lo prefiere) se accede como normal $_REQUEST['id'], $_REQUEST['data'], etc.

Y Ado be usará su nombre de archivo deseado como la información predeterminada para guardar o como correo electrónico cuando lo envíe en línea.

0

Para cualquiera que siga mirando esto, utilicé la solución encontrada here y funcionó maravillosamente. Gracias Fabrizio!

+0

Downvoted porque solo el enlace. –

1

de diálogo de descarga de archivos (PDF) con guardar y opción abierta

puntos para recordar:

  1. Volver Secuencia con correcta tamaño de la matriz del servicio
  2. Lea la arrary bytes de la corriente con la longitud de bytes correcta sobre la base de la longitud del flujo
  3. conjunto correcto contenttype

Este es el código para la secuencia de lectura y abra el diálogo de descarga de archivos para archivo PDF

private void DownloadSharePointDocument() 
{ 
    Uri uriAddress = new Uri("http://hyddlf5187:900/SharePointDownloadService/FulfillmentDownload.svc/GetDocumentByID/1/drmfree/"); 
    HttpWebRequest req = WebRequest.Create(uriAddress) as HttpWebRequest; 
    // Get response 
    using (HttpWebResponse httpWebResponse = req.GetResponse() as HttpWebResponse) 
    { 
     Stream stream = httpWebResponse.GetResponseStream(); 
     int byteCount = Convert.ToInt32(httpWebResponse.ContentLength); 
     byte[] Buffer1 = new byte[byteCount]; 
     using (BinaryReader reader = new BinaryReader(stream)) 
     { 
      Buffer1 = reader.ReadBytes(byteCount); 
     } 
     Response.Clear(); 
     Response.ClearHeaders(); 
     // set the content type to PDF 
     Response.ContentType = "application/pdf"; 
     Response.AddHeader("Content-Disposition", "attachment;filename=Filename.pdf"); 
     Response.Buffer = true; 
     Response.BinaryWrite(Buffer1); 
     Response.Flush(); 
     // Response.End(); 
    } 
} 
4

En ASP.NET 2.0 cambio de la dirección URL

http://www. server.com/DocServe.aspx?DocId=XXXXXXX 

a

http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX 

Esto funciona para Acrobat 8 ​​y el nombre de archivo SaveAs predeterminado ahora es MySaveAsFileName.pdf.

Sin embargo, debe restringir los caracteres permitidos en MySaveAsFileName (sin puntos, etc.).

4

Apache's mod_rewrite puede solucionar esto.

Tengo un servicio web con un punto final en /foo/getDoc.service. Por supuesto, Acrobat guardará los archivos como getDoc.pdf. He añadido las siguientes líneas en apache.conf:

LoadModule  RewriteModule   modules/mod_rewrite.so 
RewriteEngine on 
RewriteRule ^/foo/getDoc/(.*)$ /foo/getDoc.service  [P,NE] 

Ahora, cuando solicito /foo/getDoc/filename.pdf?bar&qux, se pone internamente reescrito para /foo/getDoc.service?bar&qux, por lo que estoy golpeando el punto final correcto del servicio web, pero Acrobat cree que va a salvar a mi archivo como filename.pdf.

Cuestiones relacionadas