且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 JSF 中保存上传的文件

更新时间:2022-10-23 21:03:01

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

InputStream input = UploadedFile.getInputStream();

您需要将其复制到文件中.您应该首先在本地磁盘文件系统上准备一个文件夹,用于存储上传的文件.例如,/path/to/uploads(在 Windows 上,它与服务器运行的位置在同一磁盘上).请注意,您应该绝对将文件存储在扩展的 WAR 文件夹甚至 IDE 项目的文件夹中,方法是使用硬编码路径或 Web 相对路径或 getRealPath()此处提到的原因.

I am uploading a file in JSF. I am using Tomahawk's <t:inputFileUpload> for this, but the same question is applicable on e.g. PrimeFaces <p:fileUpload> and JSF 2.2 <h:inputFile>.

I have the below backing bean code:

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();  
}

I am able to get the file name, type and size, but I am unable to save this file at a specific path. I can't figure out the proper way to save the uploaded file. How can I achieve this?

The getInputStream() method of the uploaded file represents the file content.

InputStream input = uploadedFile.getInputStream();

You need to copy it to a file. You should first prepare a folder on the local disk file system where the uploaded files should be stored. For example, /path/to/uploads (on Windows, that would be on the same disk as where the server runs). Note that you should absolutely not store the files in expanded WAR folder or even the IDE project's folder by using a hardcoded path or a web-relative path or getRealPath() for the reasons mentioned here Uploaded image only available after refreshing the page.

Then, you need to autogenerate the filename. Otherwise, when someone else uploads a file with coincidentally the same name later, it would be overwritten. You could use Files#createTempFile() facility to get an autogenerated filename.

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);

The path to uploads could if necessary be parameterized based on one of several ways shown in this Q&A: Recommended way to save uploaded files in a servlet application. The FilenameUtils is part of Apache Commons IO which you should already have in your classpath as it's a dependency of the Tomahawk file upload component.

Finally, just stream the uploaded file to that file (assuming Java 7):

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

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

Then, to download it back, easiest would be to register /path/to/uploads as a new webapp context or a virtual host so that all those files are available by an URL. See also Load images from outside of webapps / webcontext / deploy folder using <h:graphicImage> or <img> tag.