我有一个servlet,使用Apache Commons fileupload将上传的文件写入磁盘。这一切都很好。
它使用Tomcat在Windows和Linux服务器上运行。在Windows上,它正确处理具有非ASCII文件名的文件,并正确保存文件。
在Linux(CentOS 6)上,包含非ASCII字符时文件名未正确保存。
如果尝试过三种不同版本的文件写入。在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();
}
上传名为Это тестовый файл.txt
的文件我在Linux上获得以下结果:
版本1 :名为??? ???????? ????.txt
版本2 :Error writing file to disk: Malformed input or input contains unmappable characters: /tmp/Это тестовый файл.txt
在具有Tomcat 7和Java 7的Windows计算机上,文件名正确写为Это тестовый файл.txt
第三个版本使用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-8
并且locale
显示LANG=en_US.UTF-8
touch "Это тестовый файл.txt"
生成一个具有该名称的文件。
始终正确写入文件内容。 (当然除了根本没有写文件)。
我错过了什么或做错了什么?
答案 0 :(得分:0)
我通过将java.io.File
的所有使用转换为java.nio.Files
和java.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
代替解决了问题。