画像が文字化けして表示されるのはなぜですか?
-
09-06-2019 - |
質問
サーブレットと Apache Commons FileUpload を使用して、設定されたディレクトリにファイルをアップロードする Java コードを用意しました。文字データ(例:テキストファイル)ですが、画像ファイルは文字化けして出力されます。開くことはできますが、画像が正常に表示されません。私のコードは次のとおりです。
サーブレット
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String customerPath = "\\leetest\\";
// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
if (item.isFormField()) {
// Form field. Ignore for now
} else {
BufferedInputStream stream = new BufferedInputStream(item
.openStream());
if (stream == null) {
LOGGER
.error("Something went wrong with fetching the stream for field "
+ name);
}
byte[] bytes = StreamUtils.getBytes(stream);
FileManager.createFile(customerPath, item.getName(), bytes);
stream.close();
}
}
}
} catch (Exception e) {
throw new UploadException("An error occured during upload: "
+ e.getMessage());
}
}
StreamUtils.getBytes(stream) は次のようになります。
public static byte[] getBytes(InputStream src, int buffsize)
throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buff = new byte[buffsize];
while (true) {
int nBytesRead = src.read(buff);
if (nBytesRead < 0) {
break;
}
byteStream.write(buff);
}
byte[] result = byteStream.toByteArray();
byteStream.close();
return result;
}
そして最終的に FileManager.createFile は次のようになります。
public static void createFile(String customerPath, String filename,
byte[] fileData) throws IOException {
customerPath = getFullPath(customerPath + filename);
File newFile = new File(customerPath);
if (!newFile.getParentFile().exists()) {
newFile.getParentFile().mkdirs();
}
FileOutputStream outputStream = new FileOutputStream(newFile);
outputStream.write(fileData);
outputStream.close();
}
誰か私が間違っていることを見つけられますか?
乾杯、リー
解決
私が気に入らない点が StreamUtils.getBytes() のこのブロックにあります。
1 while (true) {
2 int nBytesRead = src.read(buff);
3 if (nBytesRead < 0) {
4 break;
5 }
6 byteStream.write(buff);
7 }
6 行目では、読み込まれたバイト数に関係なく、バッファ全体が書き込まれます。私はこれが常に当てはまるとは確信していません。より正確には次のようになります。
1 while (true) {
2 int nBytesRead = src.read(buff);
3 if (nBytesRead < 0) {
4 break;
5 } else {
6 byteStream.write(buff, 0, nBytesRead);
7 }
8 }
5 行目の「else」と、6 行目の 2 つの追加パラメータ (配列インデックスの開始位置とコピーする長さ) に注目してください。
画像などの大きなファイルの場合、バッファーがいっぱいになる前に戻ることが想像できます (おそらく、さらに待機しているのでしょう)。つまり、バッファの最後尾に残っていた古いデータを意図せず書き込むことになります。これは、バッファーが 1 バイトを超えると仮定すると、ほとんどの場合 EoF でほぼ確実に発生しますが、EoF での余分なデータが破損の原因ではない可能性があります。これは単に望ましくないだけです。
他のヒント
私はちょうど使用したいと思います コモンズアイオ 次に、IOUtils.copy(InputStream, OutputStream); を実行するだけです。
他にも便利なユーティリティ メソッドがたくさんあります。
画像が文字化けしていないか、途中でパケットがドロップしていないかを確認してください。
それがどのような違いを生むのかはわかりませんが、メソッドのシグネチャの不一致があるようです。の getBytes()
で呼び出されるメソッド doPost()
メソッドには引数が 1 つだけあります。
byte[] bytes = StreamUtils.getBytes(stream);
一方、含めたメソッド ソースには 2 つの引数があります。
public static byte[] getBytes(InputStream src, int buffsize)
それが役立つことを願っています。
元のファイルとアップロードされたファイルのチェックサムを実行して、すぐに違いがあるかどうかを確認できますか?
存在する場合は、diff を実行して、欠落しているファイルの正確な部分を特定することができます。
頭に浮かぶのは、ストリームの開始または終了、またはエンディアンです。