从Javaservlet将具有非ASCII文件名的上传文件写入磁盘
我有一个servlet,它使用ApacheCommonsFileUpload将上传的文件写入磁盘。总的来说,这一切都很好 它使用Tomcat在Windows和Linux服务器上运行。在Windows上,它可以正确处理非ASCII文件名的文件,并正确保存文件 但是,在Linux(CentOS 6)上,当包含非ASCII字符时,文件名无法正确保存 如果您尝试了三种不同版本的写入文件。在Windows中所有操作都可以,在Linux中没有一个可以,但它们会产生不同的结果 第1版:从Javaservlet将具有非ASCII文件名的上传文件写入磁盘,java,servlets,file-upload,character-encoding,Java,Servlets,File Upload,Character Encoding,我有一个servlet,它使用ApacheCommonsFileUpload将上传的文件写入磁盘。总的来说,这一切都很好 它使用Tomcat在Windows和Linux服务器上运行。在Windows上,它可以正确处理非ASCII文件名的文件,并正确保存文件 但是,在Linux(CentOS 6)上,当包含非ASCII字符时,文件名无法正确保存 如果您尝试了三种不同版本的写入文件。在Windows中所有操作都可以,在Linux中没有一个可以,但它们会产生不同的结果 第1版: String file
String fileName = URLDecoder.decode(encFilename, "UTF-8");
String filePath = uploadFolder + File.separator + fileName;
File uploadedFile = new File(filePath);
item.write(uploadedFile);
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();
}
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();
}
第2版:
String fileName = URLDecoder.decode(encFilename, "UTF-8");
String filePath = uploadFolder + File.separator + fileName;
File uploadedFile = new File(filePath);
item.write(uploadedFile);
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();
}
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();
}
上传一个名为:ª¥ª¥ª¥ª¥щфааа.txt的文件
在Linux上我得到以下结果:
版本1:一个名为:的文件????。txt
版本2:将文件写入磁盘时出错:格式错误的输入或输入包含不可复制的字符:/tmp/ª¥ª¥ª¥ª¥ª¥ª¥ª¥ª¥txt
在使用Tomcat 7和Java 7的Windows计算机上,文件名正确地写为ª¥ª¥ª¥ª¥ª¥ыыаа.txt
第三个版本使用来自的方法,不使用FileUpload。结果与版本2生成的结果相同
第3版:
String fileName = URLDecoder.decode(encFilename, "UTF-8");
String filePath = uploadFolder + File.separator + fileName;
File uploadedFile = new File(filePath);
item.write(uploadedFile);
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();
}
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”
生成具有该名称的文件
文件内容始终正确写入。(当然,没有写入任何文件的情况除外)
我遗漏了什么或做错了什么?我通过将
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
解决了这个问题。为什么要查看文件
?只需使用Path
直接尝试并调试每个版本,然后查看这三种情况下fileName
是什么