RichFaces fileupload and NullPointerException

2019-09-06 00:32发布

问题:

I'm trying to upload file to the server using rich:fileUpload, here's the code:

@Name("fileUploader")
public class FileUploader {

private byte[] fileData;

    public void uploadFileListener(UploadEvent uploadEvent) {
        fileData = uploadEvent.getUploadItem().getData();
        //other code here
    }   
}

page contains the following :

rich:fileUpload fileUploadListener="#{fileUploader.uploadFileListener}"

What I'm getting is that uploadEvent contains data about file name, size and so on... but
uploadEvent.getUploadItem().getData();
returns null...

I've already seen similar issue here... but there's no answer...

Thanks!

回答1:

Did you configured multipart-filter in components xml?

Something like this:

<web:multipart-filter create-temp-files="true" max-request-size="1000000" url-pattern="*.seam"/>

Update: I'm not completely sure if this is used for s:fileUpload or rich:fileUpload. Please check the code bellow before thinking about this configuration. By default, if I remember correctly, you should be using temp files which is the default configuration for RichFaces I think. Sorry but I don't have my project here to check it.

If you have it configured like the above your file will be saved to a temporary file (create-temp-files="true"), in this case you should access your data by using

uploadEvent.getUploadItem().getFile()

You can check if it is stored in a file with:

uploadEvent.getUploadItem().isTempFile()

Since you say that the file "metadata" is there, this looks to be the problem, you are just looking for your data in the wrong place :)

If you have it configured to false, your method should work.

Also I remember something (not completely sure) that the upload control (rich:upload) needed to be inside an h:form

Hope it helps.



回答2:

Let's put this in order:

First at all you have to define if you want your data uploaded directly in a byte[] buffer or in a temporary file and the maximum size supported. That is why you have to define two parameters in some place.

Now the place where you need to define those parameters, depends on which component you are using (i.e. seam fileUpload component or richfaces fileUpload component) and which technology is mounted for your application. Let's see:

If you are using seam framework with richfaces and you don't need ajax support (i.e. show the image being loaded once upload is finished), <s:fileUpload> would be a good choice, to configure it you have to change your seam components.xml file this way:

<web:multipart-filter create-temp-files="true"
                      max-request-size="1000000" 
                      url-pattern="*.seam" />

This means that the data you send to the server will be saved in a temporary file and that the maximum size supported is 1000000 (about 1M). More info can be found here: http://seamframework.org/Documentation/HowToUploadAndDownloadFilesInSeam

Now and using the same technology stack (seam + richfaces) but in this case you need to use ajax support. <rich:fileUpload> will be in that case your choice. To configure it just change this in the Seam Filter defined in web.xml file:

<filter>
    <filter-name>Seam Filter</filter-name>
    <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
    <init-param>
        <param-name>createTempFiles</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>maxRequestSize</param-name>
        <param-value>10000000</param-value>
    </init-param>
</filter>

Note that although the parameters are the same in both cases they are defined in different places -I imagine this is changed in JEE6 with CDDI-.

If your application don't use seam framework but it does use richfaces probably you have to define this parameters it in the corresponding richfaces filter again in web.xml.

Now the interesting part, the usage of <rich:fileUpload>. This is the relevant part of a file called BlockEdit.xhtml where the component is used:

       <rich:fileUpload
            fileUploadListener="#{blockHome.sketchListener}"
            maxFilesQuantity="1"
            reRender="table" 
            id="upload"
            immediateUpload="true"
            acceptedTypes="jpg, gif, png, bmp">
                <a:support event="onuploadcomplete" reRender="sketchImage" />
       </rich:fileUpload>

And this is the fileUploadListener of BlockHome.java

public void sketchListener(UploadEvent event) {
    UploadItem item = event.getUploadItem();
    logger.info("Sketch listener executed ...");
    if(item != null && item.getData() != null) {
        logger.info(item.getFileName()+" "+item.getFileSize());
        getInstance().getSketch().setData(item.getData());
        getInstance().getSketch().setName(item.getFileName());
        getInstance().getSketch().setContentType(item.getContentType());
        getInstance().getSketch().setSize(item.getFileSize());
    }
}

If your configuration of createTempFiles inside the seam filter in web.xml was:

    <init-param>
        <param-name>createTempFiles</param-name>
        <param-value>false</param-value>
    </init-param>

then item.getData() will be not null. But if you defined the parameter createTempFiles to true, then you should ask for item.getFile() if you want to know if it has a value. This is because the item.getData() is filled just when you decide to avoid the creation of temporary files, as stated in Richfaces demo fileUpload documentation.

FileUpload uses two init parameters which should be defined in Filter definition in web.xml:

createTempFiles boolean attribute which defines whether the uploaded files are stored in temporary files or available in listener just as byte[] data (false for this example). maxRequestSize attribute defines max size in bytes of the uploaded files (1000000 for this example).

Hope this helps