我希望能够在我的 JSF2.2 Web 应用程序中上传文件,所以我开始使用新的 <h:inputFile>
成分。
我唯一的问题是,如何指定文件将保存在服务器中的位置?我想以 java.io.File
的身份获得它们实例。这必须在支持 bean 中实现,但我不清楚如何实现。
最佳答案
JSF 不会将文件保存在任何预定义的位置。它基本上只会为您提供 javax.servlet.http.Part
风格的上传文件。临时存储在服务器内存和/或临时磁盘存储位置的幕后实例,您不必担心。
重要的是您需要阅读 Part
尽快当 bean 操作(监听器)方法被调用时。当与 HTTP 请求相关联的 HTTP 响应完成时,可以清除临时存储。换句话说,上传的文件不一定在后续请求中可用。
所以,给定一个
<h:form enctype="multipart/form-data">
<h:inputFile value="#{bean.uploadedFile}">
<f:ajax listener="#{bean.upload}" />
</h:inputFile>
</h:form>
您基本上有 2 个选项可以保存它:1. 将所有原始文件内容读入
byte[]
您可以使用 InputStream#readAllBytes()
为了这。private Part uploadedFile; // +getter+setter
private String fileName;
private byte[] fileContents;
public void upload() {
fileName = Paths.get(uploadedFile.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
try (InputStream input = uploadedFile.getInputStream()) {
fileContents = input.readAllBytes();
}
catch (IOException e) {
// Show faces message?
}
}
请注意 Path#getFileName()
.这是关于获取提交的文件名的 MSIE 修复。此浏览器错误地沿名称发送完整的文件路径,而不是仅发送文件名。如果您还没有使用 Java 9,因此不能使用
InputStream#readAllBytes()
,然后前往 Convert InputStream to byte array in Java对于所有其他转换方式 InputStream
至 byte[]
.请记住,上传文件的每个字节都会占用一个字节的服务器内存。当用户经常这样做或者很容易以这种方式滥用您的系统时,请注意您的服务器不要耗尽内存。如果您想避免这种情况,最好改用本地磁盘文件系统上的(临时)文件。
2. 或者,将其写入本地磁盘文件系统
为了将其保存到所需位置,您需要通过
Part#getInputStream()
获取内容然后 copy到 Path
代表位置。您可以以通常的方式在(ajax)操作(监听器)方法中执行此操作。这是一个在 HTML DOM 期间使用 ajax 监听器执行此操作的示例 change
事件:private Part uploadedFile; // +getter+setter
private File savedFile;
public void upload() {
String fileName = Paths.get(uploadedFile.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
savedFile = new File(uploads, fileName);
try (InputStream input = file.getInputStream()) {
Files.copy(input, savedFile.toPath());
}
catch (IOException e) {
// Show faces message?
}
}
请注意 Path#getFileName()
.这是关于获取提交的文件名的 MSIE 修复。此浏览器错误地沿名称发送完整的文件路径,而不是仅发送文件名。uploads
文件夹和 filename
完全在您的控制之下。例如。 "/path/to/uploads"
和 Part#getSubmittedFileName()
分别。请记住,任何现有文件都将被覆盖,您可能需要使用 File#createTempFile()
自动生成文件名。做 不是 使用
Part#write()
正如某些prople可能建议的那样。它基本上会重命名由 @MultipartConfig(location)
标识的临时存储位置中的文件。 .也做不是 使用 ExternalContext#getRealPath()
为了将上传的文件保存在部署文件夹中。重新部署 WAR 时,该文件将丢失,原因很简单,原始 WAR 中不包含该文件。始终将其保存在部署文件夹之外的绝对路径中。有关上传和预览功能的现场演示,请查看
<o:graphicImage>
demo on OmniFaces showcase 的最后一项.也可以看看:
关于jsf - 如何使用 JSF 2.2 上传文件 <h :inputFile>? 保存的文件在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27677397/