& # 8220; nombre & # 8221; pdf web para un mejor nombre de archivo predeterminado para guardar en Acrobat?

StackOverflow https://stackoverflow.com/questions/151079

Pregunta

Mi aplicación genera archivos PDF para el consumo del usuario. La "Disposición de contenido" El encabezado http se establece como se menciona aquí . Esto se establece en " en línea; filename = foo.pdf " ;, que debería ser suficiente para que Acrobat dé " foo.pdf " como nombre de archivo al guardar el pdf.

Sin embargo, al hacer clic en "Guardar" en el Acrobat incorporado 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 manera 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 " & amp; foo = / title.pdf " al final de la URL no afecta el nombre de archivo predeterminado.

Actualización 2: He probado ambos

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

(según lo verificado a través de Firebug) Lamentablemente, ninguno funcionó.

Una URL de muestra es

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

que se traduce en un guardado predeterminado de Acrobat como nombre de archivo de

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 y rigor reales a este caso. Por favor vota su respuesta. Esto parece estar roto en FF ( https://bugzilla.mozilla.org/show_bug. cgi? id = 433613 ) e IE pero funcionan en Opera, Safari y Chrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf

¿Fue útil?

Solución

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

Además, por lo que puedo decir, el único UA que realmente usa el nombre de archivo para type = inline es Firefox (ver caso de prueba ).

Finalmente, no es obvio que la API del complemento realmente haga que esa información esté disponible (tal vez algún chico familiarizado con la API pueda elaborarla).

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

Relacionado: vea el intento de aclarar la disposición de contenido en HTTP en draft-reschke-rfc2183-in-http - este es un trabajo temprano en progreso, apreciamos los comentarios.

Actualización: he agregado un caso de prueba , que parece indicar que el lector Acrobat el complemento no utiliza los encabezados de respuesta (en Firefox), aunque la API del complemento proporciona acceso a ellos.

Otros consejos

Establezca el nombre de archivo en ContentType también. Esto debería resolver el problema.

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

Después de configurar el encabezado de disposición de contenido, también agregue el encabezado de longitud de contenido, luego use binarywrite para transmitir el PDF.

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

Como tú, intenté y traté de hacer que esto funcionara. Finalmente renuncié a 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.

Por ejemplo:

URI antiguo:

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

Nuevo URI:

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

El encabezado resultante se ve exactamente como lo ha descrito (el tipo de contenido es application / pdf, la disposición está en línea, el nombre de archivo forma parte inútil del encabezado). Acrobat lo muestra en la ventana del navegador (sin guardar 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 del archivo del informe.

Algunas consideraciones:

Para que los nombres de archivo se vean decentes, no deberían tener caracteres escapados (es decir, sin espacios, etc.) ... lo cual es un poco limitante. Mis nombres de archivo se generan automáticamente en este caso, y antes tenían espacios en ellos, que se mostraban como '% 20' en el nombre de archivo de diálogo de guardar resultante. Acabo de reemplazar los espacios con guiones bajos, y eso funcionó.

Esta no es 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 lado del servidor que genera el PDF, es posible que deba mover el código que genera el nombre de archivo a JavaScript como parte del envío de un formulario o si proviene de una base de datos, hágalo llamada rápida ajax para obtener el nombre de archivo al crear la URL que da como resultado el PDF en línea.

Si está tomando 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 eso ayude.

Intente colocar el nombre del archivo al final de la URL, antes que cualquier otro parámetro. Esto funcionó para mí. http://www.setasign.de/support/ consejos y trucos / filename-in-browser-plugin /

En ASP.NET 2.0 cambie la URL de

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 predeterminado de SaveAs ahora es MySaveAsFileName.pdf .

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

El mod_rewrite de Apache puede resolver esto.

Tengo un servicio web con un punto final en /foo/getDoc.service . Por supuesto, Acrobat guardará los archivos como getDoc.pdf . Agregué 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 reescribe internamente en /foo/getDoc.service?bar&qux , así que estoy llegando al punto final correcto del servicio web, pero Acrobat cree que guardará mi archivo como filename.pdf .

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

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

  • crear una clase que implemente IHttpHandler
  • mapear un controlador en web.config limitado 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 gratuito (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

En lugar de adjuntar, puede probar en línea:

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

Usé en línea en una aplicación web anterior que generaba la salida de Crystal Reports en PDF y la enviaba en el navegador al usuario.

Diálogo de descarga de archivos (PDF) con la opción de guardar y abrir

Puntos para recordar:

  1. Devolver secuencia con el tamaño de matriz correcto del servicio
  2. Lea el archivo de bytes de la secuencia con la longitud de byte correcta en función de la longitud de la secuencia.
  3. establecer el tipo de contenido correcto

Aquí está el código para leer el flujo y abrir el cuadro de diálogo de descarga de archivos para archivos 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();
    }
}

Creo que esto ya se ha mencionado en uno u otro sabor, pero intentaré expresarlo con mis propias palabras.

En lugar de esto:

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

Yo uso esto:

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

En lugar de tener "exportar" procesar la solicitud, cuando llega una solicitud, busco en la URL 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 no se encuentra GeneratePDF en la URL, simplemente transmito el archivo solicitado. (tenga en cuenta que no puedo simplemente redirigir al archivo solicitado, o terminaría en un bucle sin fin)

Siempre puedes 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.

Para cualquiera que todavía esté mirando esto, utilicé la solución encontrada aquí y Trabajó maravillosamente. Gracias Fabrizio!

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

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 

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

REQUEST = MakeFriendlyURI(

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

SERVER['PHP\_SELF'],

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

SERVER['SCRIPT_FILENAME']);

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

REQUEST or

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

REQUEST = MakeFriendlyURI(

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

SERVER['PHP\_SELF'],

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

SERVER['SCRIPT_FILENAME']);

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

GET */ for ($i=0;$i < count($tmp); $i = $i+2){ $RequestArray[$tmp[$i]] = $tmp[$i+1]; } return $RequestArray; }//EO MakeFriendlyURI

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

REQUEST = MakeFriendlyURI(

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

SERVER['PHP\_SELF'],

La forma en que resolví esto (con PHP) es la siguiente:

Suponga que su URL es SomeScript.php? id = ID & amp; 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 , agregue:

<*>

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

SERVER['SCRIPT_FILENAME']);

Luego agregue esta función a SomeScript.php (o su biblioteca de funciones):

<*>

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

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

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

El enfoque que hice en este caso es NO MÁS usar el objeto de respuesta para escribir el archivo sobre la marcha. Como el PDF ya existe en el servidor, lo que hice fue redirigir mi página apuntando a ese archivo PDF. Funciona muy bien.

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

Espero que mi vaga explicación te haya dado una idea.

Créditos a Vivek .


Nginx

location /file.pdf
{
    # more_set_headers "Content-Type: application/pdf; name=save_as_file.pdf";
    add_header Content-Disposition "inline; filename=save_as_file.pdf";
    alias /var/www/file.pdf;
}

Verificar con

curl -I https://example.com/file.pdf

Firefox 62.0b5 (64 bits): OK.

Chrome 67.0.3396.99 (64 bits): OK.

IE 11: Sin comentarios.

Pruebe esto, si su ejecutable es & get; get.cgi "

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

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

Pero parece funcionar. El servidor ignora el nombre de archivo.pdf y el lector de pdf ignora el " get.cgi "

Dan

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top