5

primefaces を使用して Java EE で 2 GB を超えるファイルをアップロードしたいと考えています。一般的にはそれほど大したことではありませんが、少し問題があります。PrimeFaces の通常の方法は、ファイルをアップロードし、その UploadedFile-Object を取得し、そこから InputStream を取得してからディスクに書き込むことです。

しかし、ディスクの大きなファイルへの書き込みは、時間のかかる作業です。代わりに、アップロードされたファイルをファイル システムで見つけて、すべてのファイルを保存するフォルダーに移動したいと思います。ファイルの移動は時間を無駄にしないためです。

したがって、この質問 hereに従って、ファイルがそこに配置されるときに、PrimeFaces-Tmp-folder とサイズ制限を設定することがわかりました。これで、アップロードされたすべてのファイルがそのフォルダーに直接移動します。ポイントは、ユーザーがアップロードしている間、ディスク上にファイルがあり、後でファイルを作成しないということです。

ここまでは順調ですね。ファイルを特定して移動することができました (奇妙な名前ですが)。しかし、Primefaces Userguide (Page 187)を参照すると、この Tmp-Folder は内部で使用されているだけです。そして、Primefaces から UploadedFile-Object の内容を盗むことさえあります。私にはきれいな解決策ではないようです。

これを達成するためのヒントはありますか?

この質問も見ました。私のタイトルかもしれませんが、それは私が探しているものではありません.

編集:

コメントのため、いくつかのコード。最初に、fileUploadListener で UploadFile-Objects を収集しています。

   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 の 2 番目に、すべての UploadedFile-Object に対して 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);
    }
}
4

2 に答える 2

2

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の ID 属性であることに注意してください。<p:fileUpload>

より多くのコード:

の変更部分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);
        }

    }
}
于 2014-02-26T20:28:21.273 に答える
0

独自のフィルターを作成することにより、一時ファイルは作成されません。以下の別の投稿で私の回答を読んでください

https://stackoverflow.com/a/19581257/185022

于 2013-10-25T04:48:57.767 に答える