"名称"网络pdf更好地默认在Acrobat中保存文件名?

时间:2020-03-06 14:54:03  来源:igfitidea点击:

我的应用程序生成PDF供用户使用。如此处所述,设置" Content-Disposition" http标头。设置为" inline; filename = foo.pdf",对于Acrobat在保存pdf时提供" foo.pdf"作为文件名应该足够了。

但是,单击嵌入浏览器的Acrobat中的"保存"按钮时,要保存的默认名称不是该文件名,而是将带有斜杠的URL更改为下划线。巨大而丑陋。有没有办法影响Adobe中的默认文件名?

URL中有一个查询字符串,这是不可协商的。这可能很重要,但是在URL末尾添加"&foo = / title.pdf"不会影响默认文件名。

更新2:我都尝试过

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

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

(已通过Firebug验证)可悲的是,它们都没有起作用。

示例网址为

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

转换为默认的Acrobat另存为文件名

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

更新3:朱利安·雷施克(Julian Reschke)对此案提出了实际的见解和严谨性。请支持他的回答。
这似乎在FF(https://bugzilla.mozilla.org/show_bug.cgi?id=433613)和IE中被打破,但可以在Opera,Safari和Chrome中使用。 http://greenbytes.de/tech/tc2231/#inlwithascii文件名pdf

解决方案

我们总是可以有两个链接。一种是在浏览器中打开文档,另一种是下载(使用错误的内容类型)。这就是Gmail的功能。

还要在ContentType中设置文件名。这应该可以解决问题。

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

设置content-disposition标头后,还要添加content-length标头,然后使用binarywrite流式传输PDF。

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

除了附件,我们还可以尝试内联:

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

我在以前的Web应用程序中使用了inline,该应用程序将Crystal Reports输出生成为PDF,并将其在浏览器中发送给用户。

像我们一样,我也尽力使它起作用。最后,我放弃了这个想法,只是选择了一种解决方法。

我正在使用ASP.NET MVC Framework,因此我修改了该控制器/操作的路由,以确保提供的PDF文件是URI位置部分的最后一部分(在查询字符串之前),并传递所有内容其他在查询字符串中。

例如:

旧的URI:

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

新的URI:

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

生成的标头看起来与我们所描述的完全相同(内容类型为application / pdf,处置为内联,文件名无用地成为标头的一部分)。 Acrobat将其显示在浏览器窗口中(没有"另存为"对话框),如果用户单击" Acrobat保存"按钮,则自动填充的文件名即为报告文件名。

一些注意事项:

为了使文件名看起来不错,它们不应包含任何转义字符(即,没有空格等)...这有点限制。我的文件名是在这种情况下自动生成的,并且之前没有空格,在出现的保存对话框文件名中显示为'%20'。我只是用下划线替换了空格,然后解决了。

这绝不是最好的解决方案,但它确实有效。这也意味着我们必须具有可用的文件名才能使其成为原始URI的一部分,这可能会干扰程序的工作流程。如果当前是在生成PDF的服务器端调用过程中从数据库中生成或者从数据库检索它,则我们可能需要将生成文件名的代码移至javascript作为表单提交的一部分,或者如果它来自数据库,则将其设为构建生成内联PDF的URL时,快速ajax调用即可获取文件名。

如果要从表单上的用户输入中获取文件名,则应验证该文件名不包含转义字符,这会使用户烦恼。

希望能有所帮助。

我被重定向到这里,因为我有同样的问题。我也尝试了Troy Howard的解决方法,但似乎不起作用。

我对此所做的方法是,不再使用响应对象即时写入文件。由于PDF已经存在于服务器上,所以我要做的就是将页面重定向到该PDF文件。效果很好。

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

我希望我模糊的解释能给我们一个主意。

问题的部分原因是相关的RFC 2183并未真正说明如何处理"内联"和文件名的处置类型。

而且,据我所知,唯一真正使用type = inline的文件名的UA是Firefox(请参阅测试用例)。

最后,插件API实际上是否可以使该信息可用并不明显(也许熟悉该API的男孩可以详细说明)。

话虽如此,我已经向Adobe的人发送了一个指向该问题的指导。也许合适的人会看一下。

相关信息:请参阅草稿-reschke-rfc2183-in-http中的尝试澄清HTTP中的Content-Disposition的尝试-这是正在进行的早期工作,反馈表示赞赏。

更新:我添加了一个测试用例,它似乎表明Acrobat reader插件虽然在API中提供了对它们的访问,但并未使用响应标头(在Firefox中)。

如果可执行文件是" get.cgi",请尝试此操作

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

是的,完全疯了。服务器上没有名为" filename.pdf"的文件,在可执行文件get.cgi下根本没有目录。

但这似乎可行。服务器忽略filename.pdf,而pdf阅读器忽略" get.cgi"

我相信已经以一种或者另一种方式提到了这一点,但我会尝试用我自己的话来陈述。

而不是这样:

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

我用这个:

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

当请求进入时,我没有在"导出"过程中处理请求,而是在GeneratePDF = 1的URL中查找。如果找到,我将运行"导出"中运行的任何代码,而不是允许我的系统尝试在`/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf"位置中搜索和提供PDF。如果在URL中未找到GeneratePDF,我只发送所请求的文件。 (请注意,我不能简单地重定向到所请求的文件,否则我将陷入无尽的循环)

如果使用asp.net,则可以通过页面(url)文件名来控制pdf文件名。
正如其他用户所写的那样,当我们按"保存"按钮时选择pdf文件名时,Acrobat有点...:它带有页面名称,删除扩展名并添加" .pdf"。
因此,/ foo / bar / GetMyPdf.aspx提供了GetMyPdf.pdf。

我发现的唯一解决方案是通过asp.net处理程序管理"动态"页面名称:

  • 创建一个实现IHttpHandler的类
  • 映射到绑定到该类的web.config中的处理程序

映射1:所有页面都有一个公共基数(MyDocument_):

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

Mapping2:完全免费的文件名(在路径中需要一个文件夹):

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

这里有一些技巧(使用iTextSharp动态创建pdf):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html

我(使用PHP)解决此问题的方法如下:

假设URL是SomeScript.php?id = ID&data = DATA,而我们要使用的文件是TEST.pdf

将网址更改为" SomeScript.php / id / ID / data / DATA / EXT / TEST.pdf"。

重要的是,最后一个参数是要Adobe使用的文件名(" EXT"可以是任何东西)。确保上面的字符串BTW中没有特殊字符。

现在,在" SomeScript.php"的顶部,添加:

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

然后将此函数添加到SomeScript.php(或者函数库)中:

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

现在,像普通的$ _REQUEST ['id'],$ _ REQUEST ['data']等一样访问$ _REQUEST(如果愿意,也可以使用$ _GET)。

内联发送时,Adobe将使用我们所需的文件名作为默认的另存为或者电子邮件信息。

对于仍在查看此内容的任何人,我都使用了此处找到的解决方案,并且效果很好。谢谢Fabrizio!

带有保存和打开选项的文件下载对话框(PDF)

要记住的要点:

  • 从服务以正确的数组大小返回Stream
  • 根据流长度,从具有正确字节长度的流中读取字节数组。
  • 设置正确的内容类型

这是读取流的代码,并打开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();
    }
}

在ASP.NET 2.0中,将URL更改为

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

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

这适用于Acrobat 8​​,默认的SaveAs文件名现在是MySaveAsFileName.pdf。

但是,我们必须限制MySaveAsFileName中允许的字符(无句点等)。