2016-04-17 3 views
0

Apache Commons fileuploadを使用してアップロードしたファイルをディスクに書き込むサーブレットがあります。それは一般的にうまくいきます。JavaサーブレットからASCII以外のファイル名でアップロードされたファイルをディスクに書き込む

Tomcatを使用してWindowsとLinuxの両方のサーバーで実行されます。 Windowsでは、ASCII以外のファイル名のファイルを正しく処理し、ファイルは適切に保存されます。

ただしLinux(CentOS 6)では、非ASCII文字が含まれているとファイル名が正しく保存されません。

ファイルを書き込む3つの異なるバージョンを試したことがある場合。 Windowsではすべて動作しますが、Linuxでは何もありませんが、結果は異なります。

バージョン1:

String fileName = URLDecoder.decode(encFilename, "UTF-8"); 
String filePath = uploadFolder + File.separator + fileName; 
File uploadedFile = new File(filePath); 

item.write(uploadedFile); 

バージョン2:と呼ばれるファイルのアップロード

String fileName = URLDecoder.decode(encFilename, "UTF-8"); 
String filePath = uploadFolder + File.separator + fileName; 
File uploadedFile = new File(filePath); 

InputStream input = item.getInputStream();      
try { 
    Files.copy(input, uploadedFile.toPath()); 
} catch (Exception e) { 
    log.error("Error writing file to disk: " + e.getMessage()); 
} finally { 
    input.close(); 
} 

バージョン1Это тестовый файл.txtを私はLinux上で次のような結果を得ます:ファイル名:??? ???????? ????.txt

バージョン2Error writing file to disk: Malformed input or input contains unmappable characters: /tmp/Это тестовый файл.txt

ファイル名がЭто тестовый файл.txt

として正しく書かれているのTomcat 7とJava 7とWindowsマシンの間に3番目のバージョンはthis postからのアプローチを使用していませんFileUploadを使用します。結果は、バージョン2

によって生産されているものと同じであるバージョン3:

Part filePart = request.getPart("file"); 
String fileName = ""; 
for (String cd : filePart.getHeader("content-disposition").split(";")) { 
    if (cd.trim().startsWith("filename")) { 
     fileName = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", ""); 
     fileName = fileName.substring(fileName.lastIndexOf('/') + 1).substring(fileName.lastIndexOf('\\') + 1); // MSIE fix. 
    } 
} 

String filePath = uploadFolder + File.separator + fileName; 
File uploadedFile = new File(filePath); 

InputStream input = filePart.getInputStream();      
try { 
    Files.copy(input, uploadedFile.toPath()); 
} catch (Exception e) { 
    log.error("Error writing file to disk: " + e.getMessage()); 
} finally { 
    input.close(); 
} 

Tomcatが-Dfile.encoding=UTF-8localeで実行されているがLANG=en_US.UTF-8

touch "Это тестовый файл.txt"は、その名前のファイルを生成します示しています。

ファイルの内容は常に正しく書き込まれます。 (もちろん、ファイルがまったく書かれていない場合は除く)。

私は何が間違っているのか、間違っていますか?

+0

なぜ 'File'を使うのでしょうか?ただ単に 'Path'を直接使用してください – fge

+0

各バージョンを試してデバッグし、3つのシナリオすべてで' fileName'が何であるかを見てください – fge

答えて

0

java.io.Fileのすべての使用をjava.nio.Filesjava.nio.Pathに変換してこの問題を解決しました。だから、java.io.File APIはバグだと思われます。これを使用すると、WindowsとLinuxの両方で正常に動作します。

// The filename is passed as a URLencoded string 
String fileName = URLDecoder.decode(request.getParameter("fileName"), "UTF-8"); 
Path filePath = Paths.get(uploadFolder, fileName); 
Part filePart = request.getPart("file"); 

InputStream input = filePart.getInputStream();      
try { 
    Files.copy(input, filePath); 
} catch (Exception e) { 
    log.error("Error writing file to disk: " + e.getMessage()); 
} finally { 
    input.close(); 
} 

私がアップロードしたファイルで働いていたアプリのいくつかの他の部分で、同じ問題に遭遇し、すべての場合にjava.io.Fileを取り除き、代わりにjava.nioを使用して取得問題を解決しました。

関連する問題