在 p:graphicImage 预览中显示 p:fileupload 图像而不保存 [英] Display p:fileupload image in p:graphicImage preview without saving it

查看:25
本文介绍了在 p:graphicImage 预览中显示 p:fileupload 图像而不保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 PrimeFaces 5.3 上传 PNG 图像,我想在 中显示它的预览在保存到数据库之前.

I am using PrimeFaces 5.3 <p:fileUpload> to upload a PNG image and I would like to show a preview of it in <p:graphicImage> before saving in database.

这是一个 MCVE:

<h:form enctype="multipart/form-data">
    <p:fileUpload value="#{bean.uploadedFile}" mode="simple" />
    <p:graphicImage value="#{bean.image}" />
    <p:commandButton action="#{bean.preview}" ajax="false" value="Preview" />
</h:form>

private UploadedFile uploadedFile;

public UploadedFile getUploadedFile() {
    return uploadedFile;
}

public void setUploadedFile(UploadedFile uploadedFile) {
    this.uploadedFile = uploadedFile;
}

public void preview() {
    // NOOP for now.
}

public StreamedContent getImage() {
    if (uploadedFile == null) {
        return new DefaultStreamedContent(); 
    } else {
        return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png"); 
    }
}

backing bean 没有发生错误,图像不会在前端加载和显示.客户提到图片返回了 404 not found 错误.

No error occurring on the backing bean, and the image won't be load and display at front-end. The client mentions that the image returned a 404 not found error.

推荐答案

您的问题有两个方面.它失败是因为上传的文件内容是请求范围的,并且图像是在不同的 HTTP 请求中请求的.为了更好地理解内部工作,请仔细阅读以下密切相关的问答:

Your problem is two-fold. It failed because the uploaded file contents is request scoped and because the image is requested in a different HTTP request. To better understand the inner working, carefully read the answers on following closely related Q&A:

要解决第一个问题,需要在表单提交关联的action方法中立即读取上传的文件内容.在您的具体情况下,这看起来像:

To solve the first problem, you need to read the uploaded file contents immediately in the action method associated with the form submit. In your specific case, that would look like:

private UploadedFile uploadedFile;
private byte[] fileContents;

public void preview() {
    fileContents = uploadedFile.getContents();
}

// ...

要解决第二个问题,最好的办法是使用数据 URI 方案.这使得可以在完全相同的响应中直接渲染图像,因此您可以安全地使用 @ViewScoped bean,而不会面临上下文不活动"问题或保存 byte[] 在会话或磁盘中,以便能够在不同的请求中提供图像.浏览器对数据 URI 方案的支持 目前非常好.将整个 替换为以下内容:

To solve the second problem, your best bet is to use the data URI scheme. This makes it possible to render the image directly in the very same response and therefore you can safely use a @ViewScoped bean without facing "context not active" issues or saving the byte[] in session or disk in order to enable serving the image in a different request. Browser support on data URI scheme is currently pretty good. Replace the entire <p:graphicImage> with below:

<ui:fragment rendered="#{not empty bean.uploadedFile}">
    <img src="data:image/png;base64,#{bean.imageContentsAsBase64}" />
</ui:fragment>

public String getImageContentsAsBase64() {
    return Base64.getEncoder().encodeToString(imageContents);
}

注意:我假设您可以使用 Java 8 作为 java.util.Base64 仅在该版本中引入.如果您使用的是较旧的 Java 版本,请使用 DatatypeConverter.printBase64Binary(imageContents).

Note: I assume that Java 8 is available to you as java.util.Base64 was only introduced in that version. In case you're using an older Java version, use DatatypeConverter.printBase64Binary(imageContents) instead.

如果您碰巧使用 JSF 实用程序库 OmniFaces,您也可以使用它的 组件,而不是 ; 能够直接引用 byte[]InputStream bean 属性并呈现数据 URI.

In case you happen to use JSF utility library OmniFaces, you can also just use its <o:graphicImage> component instead which is on contrary to <p:graphicImage> capable of directly referencing a byte[] and InputStream bean property and rendering a data URI.

<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">

这篇关于在 p:graphicImage 预览中显示 p:fileupload 图像而不保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆