jsf - 如何使用 JSF 2.2 上传文件 <h :inputFile>? 保存的文件在哪里?

标签 jsf file-upload jsf-2.2 multipartform-data

我希望能够在我的 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对于所有其他转换方式 InputStreambyte[] .
请记住,上传文件的每个字节都会占用一个字节的服务器内存。当用户经常这样做或者很容易以这种方式滥用您的系统时,请注意您的服务器不要耗尽内存。如果您想避免这种情况,最好改用本地磁盘文件系统上的(临时)文件。
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 的最后一项.
也可以看看:
  • Write file into disk using JSF 2.2 inputFile
  • How to save uploaded file in JSF
  • Recommended way to save uploaded files in a servlet application
  • 关于jsf - 如何使用 JSF 2.2 上传文件 <h :inputFile>? 保存的文件在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27677397/

    相关文章:

    javascript - 通过 h :outputScript 在资源中包含 javascript

    jsf - JSF 2.2 所需的最低 Tomcat 版本

    javascript - 提交时禁用 JSF 表单字段验证

    java - 选择在扩展数据表、RichFaces 4 + JSF 2.0 中不起作用

    javascript - 使用脚本设置文件上传内容

    php - 使用 cURL 通过 POST 和 MULTIPART/FORM-DATA 执行流(逐行)文件上传

    css - 无法使用 .css 文件为 JSF 页面加载资源(图标)

    java - 访问其他 bean 或属性时 Jsf NullPointerException ManagedBean

    android - 图像在Android Studio中的Note 10和One Plus设备上旋转