我的应用会生成供用户使用的PDF。 “Content-Disposition”http标头按照here的设置进行设置。这被设置为“inline; filename = foo.pdf”,这足以让Acrobat在保存pdf时将“foo.pdf”作为文件名。
但是,单击嵌入浏览器的Acrobat中的“保存”按钮后,要保存的默认名称不是该文件名,而是带有斜杠的URL更改为下划线。巨大而丑陋。有没有办法在Adobe中影响这个默认文件名?
网址中有一个查询字符串,这是不可协商的。这可能很重要,但在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/#inlwithasciifilenamepdf
答案 0 :(得分:10)
问题的一部分是相关的RFC 2183并没有真正说明如何处理“内联”和文件名的处置类型。
另外,据我所知,实际使用type = inline文件名的唯一UA是Firefox(参见test case)。
最后,插件API实际上可以提供这些信息并不明显(也许熟悉API的人可以详细说明)。
话虽这么说,我已经向Adobe人发送了一个指向这个问题的指针;也许合适的人会看看。
相关:请参阅draft-reschke-rfc2183-in-http中的尝试澄清HTTP中的内容处置 - 这是早期的工作正在进行中,反馈意见。
更新:我添加了test case,这似乎表明Acrobat reader插件不使用响应标头(在Firefox中),尽管插件API提供了对它们的访问。
答案 1 :(得分:9)
同样在 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);
答案 2 :(得分:9)
和你一样,我试过让它发挥作用。最后我放弃了这个想法,只是选择了解决方法。
我正在使用ASP.NET MVC Framework,因此我修改了该控制器/操作的路由,以确保提供的PDF文件是URI的位置部分的最后一部分(在查询字符串之前),并传递查询字符串中的所有其他内容。
例如:
旧URI:
http://server/app/report/showpdf?param1=foo¶m2=bar&filename=myreport.pdf
新URI:
http://server/app/report/showpdf/myreport.pdf?param1=foo¶m2=bar
结果标题看起来与您所描述的完全一样(内容类型是application / pdf,处理是内联的,文件名是标题的无用部分)。 Acrobat在浏览器窗口中显示它(不保存为对话框),如果用户单击Acrobat Save按钮,则自动填充的文件名是报告文件名。
一些注意事项:
为了使文件名看起来像样,它们不应该有任何转义字符(即没有空格等)......这有点限制。在这种情况下,我的文件名是自动生成的,之前有空格,在生成的保存对话框文件名中显示为'%20'。我只是用下划线替换了空格,结果很明显。
这不是最好的解决方案,但确实有效。这也意味着您必须拥有可用的文件名才能使其成为原始URI的一部分,这可能会破坏您的程序的工作流程。如果在生成PDF的服务器端调用期间当前正在从数据库生成或检索它,则可能需要将生成文件名的代码移动到javascript作为表单提交的一部分,或者如果它来自数据库,则将其设置为快速ajax调用以在构建导致内联PDF的URL时获取文件名。
如果您从表单上的用户输入中获取文件名,则应验证该文件名不包含转义字符,这会使用户烦恼。
希望有所帮助。
答案 3 :(得分:5)
尝试在任何其他参数之前将文件名放在URL的末尾。这对我有用。 http://www.setasign.de/support/tips-and-tricks/filename-in-browser-plugin/
答案 4 :(得分:4)
在ASP.NET 2.0中,从
更改URLhttp://www. server.com/DocServe.aspx?DocId=XXXXXXX
到
http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX
这适用于Acrobat 8,默认的SaveAs文件名现在为MySaveAsFileName.pdf
。
但是,您必须限制MySaveAsFileName
中允许的字符数(不包括句号等)。
答案 5 :(得分:4)
Apache的mod_rewrite
可以解决这个问题。
我的网络服务的端点位于/foo/getDoc.service
。当然,Acrobat会将文件保存为getDoc.pdf
。我在apache.conf
中添加了以下几行:
LoadModule RewriteModule modules/mod_rewrite.so
RewriteEngine on
RewriteRule ^/foo/getDoc/(.*)$ /foo/getDoc.service [P,NE]
现在,当我请求/foo/getDoc/filename.pdf?bar&qux
时,它会被内部重写为/foo/getDoc.service?bar&qux
,因此我正在访问Web服务的正确端点,但Acrobat认为它会将我的文件保存为{{1} }。
答案 6 :(得分:2)
如果您使用asp.net,则可以通过页面(url)文件名控制pdf文件名。 正如其他用户所写,Acrobat有点......当你按“保存”按钮选择pdf文件名时:它取名页面,删除扩展名并添加“.pdf”。 所以/foo/bar/GetMyPdf.aspx给出了GetMyPdf.pdf。
我找到的唯一解决方案是通过asp.net处理程序管理“动态”页面名称:
Mapping1:所有页面都有一个共同的基数(MyDocument _):
<httpHandlers>
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Mapping2:完全免费的文件名(路径中需要一个文件夹):
<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
这里有一些提示(pdf是使用iTextSharp动态创建的):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html
答案 7 :(得分:1)
您可以尝试内联而不是附件:
Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");
我在之前的Web应用程序中使用了内联,该应用程序将Crystal Reports输出生成为PDF并将其在浏览器中发送给用户。
答案 8 :(得分:1)
我相信这已经在一种或另一种味道中提到过,但我会试着用我自己的话说出来。
而不是:
/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,我只是传输请求的文件。 (请注意,我不能简单地重定向到所请求的文件 - 否则我最终会无限循环)
答案 9 :(得分:1)
带保存和打开选项的文件下载对话框(PDF)
要记住的要点:
以下是读取流的代码,并打开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();
}
}
答案 10 :(得分:0)
您可以随时拥有两个链接。一个在浏览器中打开文档,另一个下载它(使用不正确的内容类型)。这就是Gmail的功能。
答案 11 :(得分:0)
我被重定向到这里因为我有同样的问题。我也尝试了特洛伊霍华德的解决方法,但似乎没有用。
我在这个方法上做的方法是不再使用响应对象来动态写入文件。由于PDF已存在于服务器上,我所做的是重定向指向该PDF文件的页面。效果很好。
http://forums.asp.net/t/143631.aspx
我希望我的模糊解释能给你一个想法。
答案 12 :(得分:0)
我解决这个问题的方法(使用PHP)如下:
假设您的网址为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
(或$_GET
,如果您愿意)可以像普通$_REQUEST['id']
,$_REQUEST['data']
等一样访问
当您以内联方式发送内容时,Adobe将使用您想要的文件名作为默认保存或电子邮件信息。
答案 13 :(得分:0)
对于任何仍然关注此事的人,我使用了here找到的解决方案并且效果非常好。谢谢Fabrizio!
答案 14 :(得分:0)
贷记Vivek。
$this->_id
检查
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;
}
Firefox 62.0b5(64位):确定。
Chrome 67.0.3396.99(64位):确定。
IE 11:无可奉告。
答案 15 :(得分:-1)
如果您的可执行文件是“get.cgi”
,请尝试此操作http://server,org/get.cgi/filename.pdf?file=filename.pdf
是的,这完全是疯了。服务器上没有名为“filename.pdf”的文件,可执行文件get.cgi下有目录。
但似乎有效。服务器忽略filename.pdf,pdf阅读器忽略“get.cgi”
丹