Stream closed Exception

2019-08-29 08:05发布

I'm getting Stream is closed Exception when I'm going to save the uploaded image. I'm tring to preview graphicImage of uploaded image the before save. This operation is working. But I can't save the image. Here is my code:

private InputStream in;
private StreamedContent filePreview;
// getters and setters

public void upload(FileUploadEvent event)throws IOException { 
    // Folder Creation for upload and Download
    File folderForUpload = new File(destination);//for Windows
    folderForUpload.mkdir();
    file = new File(event.getFile().getFileName());
    in = event.getFile().getInputstream();
    filePreview = new DefaultStreamedContent(in,"image/jpeg");
    FacesMessage msg = new FacesMessage("Success! ", event.getFile().getFileName() + " is uploaded.");  
    FacesContext.getCurrentInstance().addMessage(null, msg);
}

public void setFilePreview(StreamedContent fileDownload) {
    this.filePreview = fileDownload;
}

public StreamedContent getFilePreview() {
    return filePreview;
}

public void saveCompanyController()throws IOException{
    OutputStream out  = new FileOutputStream(getFile());
    byte buf[] = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0)
        out.write(buf, 0, len);
    FileMasterDO fileMasterDO=new FileMasterDO();
    fileMasterDO.setFileName(getFile().getName());
    fileMasterDO.setFilePath(destination +file.getName());
    fileMasterDO.setUserMasterDO(userMasterService.findUserId(UserBean.getUserId()));
    fileMasterDO.setUpdateTimeStamp(new Date());
    in.close();
    out.flush();
    out.close();
    fileMasterService.save(filemaster);
}

The bean is in the session scope.

1条回答
▲ chillily
2楼-- · 2019-08-29 08:48

You're trying to read an InputStream twice (the first time is in DefaultStreamedContent constructor of upload method and the second time is in the copy loop of the save method). This is not possible. It can be read only once. You need to read it into a byte[] first and then assign it as a bean property so that you can reuse it for both the StreamedContent and the save.

Make sure that you never hold external resources such as InputStream or OutputStream as a bean property. Remove them all from the current and other beans where applicable and use byte[] to hold the image's content as property.

In your particular case, you need to fix it as follows:

private byte[] bytes; // No getter+setter!
private StreamedContent filePreview; // Getter only.

public void upload(FileUploadEvent event) throws IOException {
    InputStream input = event.getFile().getInputStream();

    try {
        IOUtils.read(input, bytes);
    } finally {
        IOUtils.closeQuietly(input);
    }

    filePreview = new DefaultStreamedContent(new ByteArrayInputStream(bytes), "image/jpeg");
    // ...
}

public void saveCompanyController() throws IOException {
    OutputStream output = new FileOutputStream(getFile());

    try {
        IOUtils.write(bytes, output);
    } finally {
        IOUtils.closeQuietly(output);
    }

    // ...
}

Note: IOUtils is from Apache Commons IO, which you should already have in the classpath as it's a dependency of <p:fileUpload>.

查看更多
登录 后发表回答