PDF を生成するために、Internet Explorer の URL 制限を回避しようとしています (詳細については、この Microsoft サポート記事を参照してください)。
クライアント側のJSにPDFのバイトストリームを表すbase-64でエンコードされた文字列があります。Firefox と Chrome の場合、先頭に文字列を追加して PDF を表示するdata:application/pdf;base64,
と、ブラウザは問題なくデータ URI をレンダリングします。
Internet Explorer の場合、文字列を POST でサーブレットに送り返して、コンテンツ タイプが「application/pdf」のバイト ストリームを返すことができるようにしようとしています。クライアント側のリクエストで実際の PDF コンテンツを渡していることを除いて、次の質問で提案されているソリューションに従っています。
私の HTTP POST は次のようになります。
var pdf; // base-64 encoded string in this variable
$http.post("/convert/pdf", {
params: {
base64pdf: pdf
}
}, {
responseType : "arraybuffer"
}).then( function onSuccess(result) {
var file = new Blob([result.data], {type: 'application/pdf'});
window.navigator.msSaveOrOpenBlob(file, "result.pdf");
},
function onFailure() { /* log and do failure case stuff */ });
私のサーバーは Java spring-webmvc サービスを実行しています。Convert コントローラーは次のようになります。
@Controller
@RequestMapping(value = "/convert", produces = "application/pdf")
public class ConvertController {
@RequestMapping(value = "/pdf", method = RequestMethod.POST)
public ResponseEntity<byte[]> generatePdf(
@RequestParam(value="base64pdf", required=true) String base64encodedDataUri,
HttpServletRequest request) {
byte[] bytes = Base64.decodeBase64(base64encodedDataUri);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = "test.pdf";
headers.setContentDispositionFormData(filename, filename);
ResponseEntity<byte[]> response = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
return response;
}
// other methods
}
コントローラーのコードは、この回答に基づいています。問題はないと思います。単体テストで問題なくテストでき、Swagger API インターフェースを介して POST リクエストを送信します。
問題はこれです。$http.post
IE でこれをトリガーすると、結果は常にエラー コールバックになり、常にHTTP 400 エラーになります。
私は次のことを観察しました:
IE 11 の開発者ツール ネットワーク トラフィック キャプチャを使用して、リクエストが行われていることを確認できます。リクエストには、base-64 でエンコードされた完全で正しい文字列が params に含まれており、これはリクエスト ボディにあります。
リクエスト ヘッダーは次のようになります。
Request POST /convert/pdf HTTP/1.1 Content-Type アプリケーション/json;charset=utf-8 application/json、text/plain、*/* を受け入れる リファラー localhost:8080/ Accept-Language en-US Accept-Encoding gzip、デフレート ユーザーエージェント Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) Gecko のような ホスト localhost:8080 コンテンツの長さ 5699 DNT 1 接続キープアライブ キャッシュ継続 ロールのキャッシュなし
- 応答ヘッダーには次のように表示されます。
応答 HTTP/1.1 400 不正な要求 サーバー Apache-Coyote/1.1 アクセス制御許可オリジン * Access-Control-Allow-Methods POST、GET、OPTIONS、DELETE Access-Control-Max-Age 3600 Access-Control-Allow-Headers x-requested-with コンテントタイプ申請書/pdf コンテンツの長さ 98 日付 2015 年 12 月 7 日(月)21:54:32 GMT 接続を閉じる
応答本文に無効な PDF が含まれています。技術的には、開発者ツールはそれをレンダリングできないと言います。保存すると、保存される PDF は有効な PDF ではありません。
編集: Tomcat8 でログを記録したところ、Spring が要求に「base64pdf」パラメーターが欠落していると不平を言っていることがわかりました。
2015-12-08 02:29:32,514 INFO [http-nio-8080-exec-4] INFO Required String parameter 'base64pdf' is not present
org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'base64pdf' is not present
だから私は本当に2つの質問があります:
base64pdf
どのようにパラメータを失うのですか? パラメータなどに最大長はありますか?data: { base64pdf : pdf }
この質問に表示されているオリジナルと、以下のユーザー chenzhenjia によって提案されているように、パラメーターを経由して渡すことの両方を試しました。この PDF 呼び出しを IE で動作させるにはどうすればよいですか? 一方で、上記で何が間違っているのか知りたいのですが、率直に言って、クライアント側にあるこのbase-64でエンコードされた文字列をPDF. (つまり、これがXY 問題であり、間違ったツリーを鳴らしている場合は、それも知りたいです。)
私は使用しています:
- AngularJS 1.4.8
- 春 4.2.3.RELEASE
- Java 8
- トムキャット 8