java - 如何移动 Primefaces-Upload-Temp-Files 而不是进行耗时的复制过程?

标签 java file-upload jsf-2 primefaces

我想使用 primefaces 使用 Java EE 上传大于 2 GB 的文件。一般来说,这没什么大不了的,但我有一个小问题。 PrimeFaces 通常的方法是上传一个文件,拥有该 UploadedFile-Object,从中获取 InputStream,然后将其写入磁盘。

但是将大文件写入磁盘是一项耗时的任务。相反,我想在文件系统中找到上传的文件,然后将其移动到我存储所有文件的文件夹中,因为移动文件不会浪费时间。

因此,根据 this question here我想出了设置 PrimeFaces-Tmp-folder 和大小限制,当文件将放在那里。现在每个上传的文件都直接进入该文件夹。关键是,我现在在磁盘上有一个文件,而用户正在上传 - 而不是之后创建它。

到目前为止,还不错。我可以识别文件并移动它(尽管它有一个奇怪的名字)。但指向Primefaces Userguide (Page 187) ,这个 Tmp-Folder 只是内部使用。我什至会从 Primefaces 窃取 UploadedFile-Object 的内容。对我来说似乎不是一个干净的解决方案。

有什么实现方法的提示吗?

我还看到了this question .也可以是我的标题,但这不是我要找的。

编辑:

由于注释,一些代码。首先,我在 fileUploadListener 中收集上传文件对象:

   public void handleFileUpload(FileUploadEvent event) throws IOException {
    FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
    FacesContext.getCurrentInstance().addMessage(null, msg);

    getUploadedFilesDTO().add(new UploadedFileDTO(event.getFile(), uploadedFilesCounter));
    uploadedFilesCounter++;

}

第二,在 EJB 中,我为每个上传的文件对象调用 copyFile:

private void copyFile(UploadedFile uploadedFile, String randomFilename) throws IOException {


    InputStream originalFile = uploadedFile.getInputstream();
    OutputStream fileOutput = null;

    try {
        fileOutput = new FileOutputStream("/pvtfiles/" + randomFilename);
        IOUtils.copy(originalFile, fileOutput);
    } finally {
        IOUtils.closeQuietly(fileOutput);
        IOUtils.closeQuietly(originalFile);
    }
}

最佳答案

我能够按照 AZ_ 的建议编写自定义过滤器并添加以下内容来做到这一点:

FileItem fileItem = multipartRequest.getFileItem("form:fileUpload");
File file = new File(uploadDir + "/" + fileItem.getName());
fileItem.write(file);

诀窍是使用 MultipartRequest对象获得 FileItem目的。 FileItemwrite方法可用于将文件保存在不同的位置或使用不同的名称。根据文档,某些实现可能仍会使用副本来执行此操作,但我正在使用的 (Apache Commons 1.3) 似乎会根据需要通过重命名/移动来执行此操作。请注意 getFileItem 中使用的字符串找到 FileItem是来自 <p:fileUpload> 的 ID 属性标签。

更多代码:

web.xml 的修改部分:

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>some.package.CustomFileUploadFilter</filter-class>
</filter>

示例 jsf:

<h:form id="form">
    <h:panelGrid columns="1" class="blockleft">
        <p:fileUpload
            id="fileUpload"
            auto="true" />
    </h:panelGrid>
</h:form>

示例自定义过滤器类:

package some.package;

import java.io.File;
import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.primefaces.webapp.MultipartRequest;
import org.primefaces.webapp.filter.FileUploadFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomFileUploadFilter extends FileUploadFilter {

    private static final Logger LOG = LoggerFactory.getLogger(CustomFileUploadFilter.class);

    private String thresholdSize;

    private String uploadDir;

    private final static String THRESHOLD_SIZE_PARAM = "thresholdSize";

    private final static String UPLOAD_DIRECTORY_PARAM = "uploadDirectory";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        thresholdSize = filterConfig.getInitParameter(THRESHOLD_SIZE_PARAM);
        uploadDir = filterConfig.getInitParameter(UPLOAD_DIRECTORY_PARAM);

        LOG.info("CatalogFileUploadFilter initiated successfully");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);

        if (isMultipart) {
            LOG.info("Parsing file upload request");

            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();

            if (thresholdSize != null){
                diskFileItemFactory.setSizeThreshold(Integer.valueOf(thresholdSize).intValue());
            }
            if (uploadDir != null){
                diskFileItemFactory.setRepository(new File(uploadDir));
            }

            ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
            MultipartRequest multipartRequest = new MultipartRequest(httpServletRequest, servletFileUpload);

            try {
                FileItem fileItem = multipartRequest.getFileItem("form:fileUpload");
                File file = new File("path/to/location/" + fileItem.getName());
                fileItem.write(file);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            LOG.info("File upload request parsed successfully, continuing with filter chain with a wrapped multipart request");

            filterChain.doFilter(multipartRequest, response);
        } else {
            filterChain.doFilter(request, response);
        }

    }
}

关于java - 如何移动 Primefaces-Upload-Temp-Files 而不是进行耗时的复制过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18548977/

相关文章:

Java Swing.Timer 获取实时毫秒数

java - 有哪些高性能、可扩展的方法来解析来自 http ://bit. ly 的链接

jsf - 警告 : Multiple JSF Applications found on same ClassLoader. 无法安全地确定要使用哪个 FactoryManager 实例

http - 如何在 Erlang Web 服务器中处理非常大的文件上传?

java - JSF 2.0 web.xml 错误页面状态代码

exception-handling - JSF PostConstruct 异常处理 - 重定向

java - Java-同步和启动线程

java - 使用 HikariCP 配置 hibernate

mysql - upload_max_filesize 即使在修改 php.ini 后也没有改变

javascript - 使用 jquery 进行多文件上传,有限制