1年でPCを3台クラッシュさせました。
原因はこの静電気体質にあるのではというもっぱらの評判。
生涯メモリ増設作業はしないと心に決めた。絶対やらかす。
本題
1)HTTPS通信でPDFダウンロードに失敗する
IE8のhttpsを使用している場合、キャッシュコントロール上の問題でバグがある模様。
SSL経由でファイルのダウンロードをInternet Explorerキャッシュコントロールヘッダーが機能しません
これね。めっちゃやられた。
社内環境がWin8のIE9以上しかなく、かつ、客先にXPが残っていたという始末。
客先というか。客先の客先というか。まじかよもうサポート終わるっつの。
とりあえず
Cache-Control: public
Pragma: public
これをヘッダーに追加するだけで無事解決。
通常ページはキャッシュ不可にしておいたのが、まさかこんなところでネックになるとは。
2)特定のPDFのダウンロードでPDFが壊れる
これはまあ普通にプログラムミスなんですけども。
ファイルダウンロード時に使用していたストリームが原因。
ファイルが格納されているのがPostgreSQLのカラム内なのでバイト配列を直接ByteArrayInputStreamに乗っけて、4096バイトずつOutput側に流すってやってました。
こんな感じ。(outはServletOutputStream)
while(in.read(outputByte, 0, 4096) != -1){
out.write(outputByte, 0, 4096);
}
こうすると、どうも圧縮されてないPDFとかの場合は何の問題もないんだけど、
圧縮されてるPDF(いわゆる最適化されたPDF)になると、最後が4096未満の場合に
足りないバイト分を再ロードしちゃうみたいで末尾に不要なデータがひっつき、
不正ファイルという扱いになってAdobeさんからは読めなくなる。
(Chrome上のビューアーだと読めた。EOFをちゃんと解析してくれてるっぽい)
いまだによく理解できてないのは、なぜ最適化されていないPDFではうまくいくのか?ってこと
最適化されてると、ディスク上の容量と実際の容量が異なって見えるけど、この辺に違いがあるのかね。
ダウンロードした不正ファイル見ると、ディスク上の容量も元の容量に戻ってるし。
なんにしろ、inから呼んだバイト数をきっちりチェックして、outに渡してやるために
以下のように処理を変更。
// 入力ストリームから固定サイズバッファを読み込む。
byte[] buffer = new byte[4096];
byRead = in.read(buffer);
if (byRead > 0) {
// 出力ストリームにバッファを書き込む。
out.write(buffer, 0, byRead);
out.flush();
}
ついでに、outはBufferedOutputStreamでラップするようにしておいた。
これで解決。
原因はこの静電気体質にあるのではというもっぱらの評判。
生涯メモリ増設作業はしないと心に決めた。絶対やらかす。
本題
1)HTTPS通信でPDFダウンロードに失敗する
IE8のhttpsを使用している場合、キャッシュコントロール上の問題でバグがある模様。
SSL経由でファイルのダウンロードをInternet Explorerキャッシュコントロールヘッダーが機能しません
これね。めっちゃやられた。
社内環境がWin8のIE9以上しかなく、かつ、客先にXPが残っていたという始末。
客先というか。客先の客先というか。まじかよもうサポート終わるっつの。
とりあえず
Cache-Control: public
Pragma: public
これをヘッダーに追加するだけで無事解決。
通常ページはキャッシュ不可にしておいたのが、まさかこんなところでネックになるとは。
2)特定のPDFのダウンロードでPDFが壊れる
これはまあ普通にプログラムミスなんですけども。
ファイルダウンロード時に使用していたストリームが原因。
ファイルが格納されているのがPostgreSQLのカラム内なのでバイト配列を直接ByteArrayInputStreamに乗っけて、4096バイトずつOutput側に流すってやってました。
こんな感じ。(outはServletOutputStream)
while(in.read(outputByte, 0, 4096) != -1){
out.write(outputByte, 0, 4096);
}
こうすると、どうも圧縮されてないPDFとかの場合は何の問題もないんだけど、
圧縮されてるPDF(いわゆる最適化されたPDF)になると、最後が4096未満の場合に
足りないバイト分を再ロードしちゃうみたいで末尾に不要なデータがひっつき、
不正ファイルという扱いになってAdobeさんからは読めなくなる。
(Chrome上のビューアーだと読めた。EOFをちゃんと解析してくれてるっぽい)
いまだによく理解できてないのは、なぜ最適化されていないPDFではうまくいくのか?ってこと
最適化されてると、ディスク上の容量と実際の容量が異なって見えるけど、この辺に違いがあるのかね。
ダウンロードした不正ファイル見ると、ディスク上の容量も元の容量に戻ってるし。
なんにしろ、inから呼んだバイト数をきっちりチェックして、outに渡してやるために
以下のように処理を変更。
// 入力ストリームから固定サイズバッファを読み込む。
byte[] buffer = new byte[4096];
byRead = in.read(buffer);
if (byRead > 0) {
// 出力ストリームにバッファを書き込む。
out.write(buffer, 0, byRead);
out.flush();
}
ついでに、outはBufferedOutputStreamでラップするようにしておいた。
これで解決。