如何在 JSF 中保存上传的文件
Posted
技术标签:
【中文标题】如何在 JSF 中保存上传的文件【英文标题】:How to save uploaded file in JSF 【发布时间】:2012-12-22 02:53:27 【问题描述】:我在 JSF 中上传一个文件。我为此使用 Tomahawk 的 <t:inputFileUpload>
,但同样的问题适用于例如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();
我能够获取文件名、类型和大小,但我无法将此文件保存在特定路径。我想不出保存上传文件的正确方法。我怎样才能做到这一点?
【问题讨论】:
添加更多细节。发布完整代码 @Abin 我用代码编辑过,我得到了文件名,但是我怎么把它上传到服务器上,你知道吗? 你正在使用 Myfaces..对吗? 是的,JSF1.1。我想用特定的url存储本地文件@server 其实我没有错误,但是我使用带有上传文件的getInputStream()
方法代表文件内容。
InputStream input = uploadedFile.getInputStream();
您需要将其复制到文件中。您应该首先在本地磁盘文件系统上准备一个文件夹,用于存储上传的文件。例如,/path/to/uploads
(在 Windows 上,这将与服务器运行在同一个磁盘上)。请注意,出于Uploaded image only available after refreshing the page 中提到的原因,您应该绝对不使用硬编码路径或 Web 相对路径或 getRealPath()
将文件存储在扩展的 WAR 文件夹甚至 IDE 项目的文件夹中。
然后,您需要自动生成文件名。否则,当其他人稍后上传巧合同名的文件时,它将被覆盖。您可以使用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);
如有必要,可以根据本问答中显示的几种方法之一对上传路径进行参数化:Recommended way to save uploaded files in a servlet application。 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 访问。另见Load images from outside of webapps / webcontext / deploy folder using <h:graphicImage> or <img> tag。
【讨论】:
thanx,如果我想一次选择多个文件,那么我需要选择什么?<t:inputFileUpload>
无法做到这一点,它会生成一个普通的旧 html4 <input type="file">
。这仅适用于 Flash 或 HTML5 <input type="file" multiple="true">
。 RichFaces 和 PrimeFaces 提供了这样的组件。例如。 showcase.richfaces.org/richfaces/… 和 primefaces.org/showcase/ui/fileUploadMultiple.jsf
谢谢,很抱歉越来越多的质疑,但还有其他方式使用 <t:inputFileUpload>
组件或在<h:dataTable>
或<t:dataList>
中使用它,并由UploadedFile
集合支持。
@Ced:因为在写入之前物理创建了一个空的临时文件(因此已经存在)。它以这种方式工作,因此系统可以保证在创建和写入之间其他线程不会创建其他具有巧合同名的临时文件。【参考方案2】:
PrimeFaces 使用两个文件上传解码器来上传 p:fileupload 的内容
-
NativeFileUploadDecoder
CommonsFileUploadDecoder
NativeFileUploadDecoder 是默认的上传解码器,它需要 servlet 容器 3.0。因此,如果您的 servlet 容器小于 3,那么它将无法与您一起使用。 还有一些应用服务器限制使用多部分内容
因此,如果您因任何原因对本机上传解码器有问题,您必须使用另一个解码器,即“CommonsFileUploadDecoder”
CommonsFileUploadDecoder 依赖于 Apache 公共库 所以你必须把 commons-fileupload 和 commons-io jars 放在你的类路径中 版本取决于您的 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>
【讨论】:
***.com/questions/8875818/… 那个帖子的答案 PrimeFaces 文档中的所有内容都没有吗?以上是关于如何在 JSF 中保存上传的文件的主要内容,如果未能解决你的问题,请参考以下文章