21

我在 JSF 中上传一个文件。我<t:inputFileUpload>为此使用了 Tomahawk,但同样的问题也适用于 PrimeFaces<p:fileUpload>和 JSF 2.2<h:inputFile>等。

我有以下支持 bean 代码:

private UploadedFile uploadedFile; // +getter+setter

public String save() throws IOException {
    String name = uploadedFile.getName();
    System.out.println("File name: " + name);

    String type = uploadedFile.getContentType();
    System.out.println("File type: " + type);

    long size = uploadedFile.getSize();
    System.out.println("File size: " + size);  

    InputStream stream = uploadedFile.getInputStream();
    byte[] buffer = new byte[(int) size];  
    stream.read(buffer, 0, (int) size);  
    stream.close();  
}

我能够获取文件名、类型和大小,但无法将此文件保存在特定路径。我想不出保存上传文件的正确方法。我怎样才能做到这一点?

4

2 回答 2

59

上传文件的getInputStream()方法代表文件内容。

InputStream input = uploadedFile.getInputStream();

您需要将其复制到文件中。您应该首先在本地磁盘文件系统上准备一个文件夹,用于存储上传的文件。例如,/path/to/uploads(在 Windows 上,这将与服务器运行在同一个磁盘上)。请注意,您绝对不应使用硬编码路径或 Web 相对路径将文件存储在扩展的 WAR 文件夹甚至 IDE 项目的文件夹中,或者getRealPath()出于此处提到的原因Uploaded image only available after refresh the page

然后,您需要自动生成文件名。否则,当其他人稍后上传巧合同名的文件时,它将被覆盖。您可以使用Files#createTempFile()工具来获取自动生成的文件名。

Path folder = Paths.get("/path/to/uploads");
String filename = FilenameUtils.getBaseName(uploadedFile.getName()); 
String extension = FilenameUtils.getExtension(uploadedFile.getName());
Path file = Files.createTempFile(folder, filename + "-", "." + extension);

如有必要,可以根据本问答中所示的几种方法之一对上传路径进行参数化:在 servlet 应用程序中保存上传文件的推荐方法。它FilenameUtils是 Apache Commons IO 的一部分,您应该已经在类路径中拥有它,因为它是 Tomahawk 文件上传组件的依赖项。

最后,只需将上传的文件流式传输到该文件(假设 Java 7):

try (InputStream input = uploadedFile.getInputStream()) {
    Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);
}

System.out.println("Uploaded file successfully saved in " + file);

然后,要下载它,最简单的方法是注册/path/to/uploads为新的 webapp 上下文或虚拟主机,以便所有这些文件都可以通过 URL 获得。另请参阅使用 <h:graphicImage> 或 <img> 标签从 webapps/webcontext/deploy 文件夹外部加载图像

于 2013-01-08T11:44:15.860 回答
1

PrimeFaces 使用两个文件上传解码器来上传 p:fileupload 的内容

  1. NativeFileUploadDecoder
  2. CommonsFileUploadDecoder

NativeFileUploadDecoder 是默认的上传解码器,它需要 servlet 容器 3.0。因此,如果您的 servlet 容器小于 3,那么它将无法与您一起使用。还有一些应用服务器限制使用多部分内容

因此,如果由于任何原因您对本机上传解码器有问题,您必须使用另一个解码器,即“CommonsFileUploadDecoder”

CommonsFileUploadDecoder 依赖于 Apache 公共库,因此您必须将commons-fileupload 和 commons-io jar放在类路径中,版本取决于您的 primefaces 版本,但 1.3 和 2.2 分别适用于我。

要使用 CommonsFileUploadDecoder 你必须使用过滤器

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

仅等待过滤器将不起作用,因为在过滤器内部它会检查上传器是否未提供,并且它至少检测到 JSF 2.2,因此它将绕过对默认解码器“Native”的请求,然后它也不适用于您

要强制过滤器使用通用解码器,您必须将以下上下文参数放入 web.xml

<context-param>
<param-name>primefaces.UPLOADER</param-name>
   <param-value>commons</param-value>
</context-param>
于 2018-05-16T06:19:55.127 回答