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でラップするようにしておいた。
これで解決。