私のアプリはユーザーが使用するPDFを生成します。 「Content-Disposition」httpヘッダーは、前述のように設定されています here 。これは "inline; filename = foo.pdf"に設定されます。これは、AcrobatがPDFを保存するときにファイル名として "foo.pdf"を指定するのに十分なはずです。
ただし、ブラウザに埋め込まれたAcrobatの[保存]ボタンをクリックすると、保存するデフォルトの名前はそのファイル名ではなく、スラッシュを含むURLがアンダースコアに変更されます。巨大で醜い。 Adobeでこのデフォルトのファイル名に影響を与える方法はありますか?
IS 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で確認済み)残念ながら、どちらも機能しませんでした。
サンプルURLは
/ 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=43361 )とIEで壊れているようですが、Opera、Safariで動作しますおよびChrome http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf
問題の一部は、関連する RFC 218 が、「インライン」の処理タイプとファイル名の処理方法を実際に述べていないことです。
また、私の知る限り、type = inlineのファイル名を実際に使用しているUAはFirefoxのみです( test case を参照)。
最後に、プラグインAPIが実際にその情報を利用できるようにすることは明らかではありません(おそらくAPIに精通している誰かが詳しく説明できるでしょう)。
そうは言っても、私はこの質問へのポインタをアドビの人に送りました。たぶん、適切な人々が見るでしょう。
関連: draft-reschke-rfc2183-in-http のHTTPでContent-Dispositionを明確にする試みを参照してください。これは進行中の初期の作業であり、フィードバックを歓迎します。
更新: テストケース を追加しました。これは、Acrobatリーダープラグインが(Firefoxで)応答ヘッダーを使用しないことを示しているようですが、プラグインAPIはそれらにアクセスできます。
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);
あなたのように、私はこれを動かしてみました。最後に、私はこの考えをあきらめ、回避策を選びました。
私はASP.NET MVCフレームワークを使用しているので、そのコントローラー/アクションのルートを変更して、提供される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呼び出し。
フォーム上のユーザー入力からファイル名を取得する場合は、エスケープ文字が含まれていないことを検証する必要があります。これにより、ユーザーが煩わしくなります。
お役に立てば幸いです。
他のパラメータの前に、URLの最後にファイル名を配置してください。これでうまくいきました。 http://www.setasign.de/support/tips-and-tricks/filename-in-browser-plugin/
Apacheのmod_rewrite
はこれを解決できます。
/foo/getDoc.service
にエンドポイントがあるWebサービスがあります。もちろん、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はファイルをfilename.pdf
として保存すると認識します。
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
で使用できる文字を制限する必要があります(ピリオドなどは使用できません)。
Asp.netを使用する場合、ページ(url)ファイル名を介してPDFファイル名を制御できます。他のユーザーが書いたように、Acrobatは少しだけ...「保存」ボタンを押してPDFファイル名を選択すると、ページ名を取得し、拡張子を削除して「.pdf」を追加します。したがって、/ foo/bar/GetMyPdf.aspxはGetMyPdf.pdfを提供します。
私が見つけた唯一の解決策は、asp.netハンドラーを介して「動的」ページ名を管理することです。
マッピング1:すべてのページに共通の基数(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
添付ファイルの代わりにインラインで試すことができます:
Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");
Crystal Reports出力をPDFに生成する以前のWebアプリケーションでインラインを使用し、それをブラウザーでユーザーに送信しました。
私はこれがすでにいくつかのフレーバーで言及されていると思いますが、私は自分の言葉でそれを述べようとします。
これよりも:
/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を調べます。見つかった場合、システムがPDFロケーションで/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf
。 URLにGeneratePDFが見つからない場合は、要求されたファイルを送信するだけです。 (要求されたファイルに単純にリダイレクトできないことに注意してください。そうしないと、無限ループに陥ってしまいます)
保存して開くオプションを備えたファイルダウンロードダイアログ(PDF)
覚えておくべきポイント:
これは、ストリームを読み取り、PDF fileのファイルダウンロードダイアログを開く
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();
}
}
同じ問題があるので、ここにリダイレクトされました。トロイハワードの回避策も試しましたが、うまくいかないようです。
私がこれに対して行ったアプローチは、応答オブジェクトを使用せずにオンザフライでファイルを書き込むことです。 PDFはすでにサーバー上に存在するので、私が行ったのは、そのページを指すようにページをリダイレクトすることでしたPDFファイル。うまく動作します。
http://forums.asp.net/t/143631.aspx
私の漠然とした説明があなたにアイデアを与えてくれれば幸いです。
あなたは常に2つのリンクを持つことができます。 1つはブラウザー内でドキュメントを開き、もう1つはそれをダウンロードします(正しくないコンテンツタイプを使用)。これがGmailの機能です。
まだこれを見ている人のために、私は見つかった解決策を使用しました here とそれは素晴らしく機能しました。ファブリツィオ、ありがとう!
私がこれを(PHPで)解決した方法は次のとおりです:
URLがSomeScript.php?id=ID&data=DATA
で、使用するファイルがTEST.pdf
だとします。
URLをSomeScript.php/id/ID/data/DATA/EXT/TEST.pdf
に変更します。
最後のパラメーターは、アドビに使用させたいファイル名であることが重要です( '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']
などのようにアクセスできるようになりました。
アドビでは、インラインで送信するときに、希望するファイル名をデフォルトの別名保存またはメール情報として使用します。
Vivek へのクレジット。
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;
}
確認する
curl -I https://example.com/file.pdf
Firefox 62.0b5(64ビット):OK。
Chrome 67.0.3396.99(64ビット):OK。
IE 11:コメントはありません。