【问题标题】:Display p:fileupload image in p:graphicImage preview without saving it在 p:graphicImage 预览中显示 p:fileupload 图像而不保存它
【发布时间】:2016-12-13 12:22:56
【问题描述】:

我正在使用 PrimeFaces 5.3 <p:fileUpload> 上传 PNG 图像,我想在保存到数据库之前在 <p:graphicImage> 中显示它的预览。

这是一个 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 错误。

【问题讨论】:

  • 你说上传有效,那么这个问题file-uploadgraphic-image 无关而不是graphic-image
  • 因为byte[]的来源来自上传内容,所以我得到了上传内容byte[],但是当我使用上传内容显示在网页上时,它不会显示并说找不到资源
  • 所以你的意思是,如果你手动将一个字节[]放入数据库中,而不是通过文件上传,它可以工作吗?
  • 对不起先生,您误解了我的问题,我还没有尝试数据库,因为它不能通过文件上传工作

标签: jsf file-upload primefaces preview graphicimage


【解决方案1】:

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

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

private UploadedFile uploadedFile;
private byte[] fileContents;

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

// ...

要解决第二个问题,最好的办法是使用数据 URI 方案。这使得可以直接在相同的响应中渲染图像,因此您可以安全地使用@ViewScoped bean,而不会遇到“上下文不活动”问题或将byte[] 保存在会话或磁盘中以启用图像服务在不同的请求中。 Browser support on data URI scheme 目前还不错。将整个 &lt;p:graphicImage&gt; 替换为以下内容:

<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)

如果您碰巧使用 JSF 实用程序库 OmniFaces,您也可以只使用它的 &lt;o:graphicImage&gt; 组件,这与 &lt;p:graphicImage&gt; 能够直接引用 byte[]InputStream bean 属性和呈现数据 URI。

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

【讨论】:

  • 谢谢@BalusC 问题现在已经完全验证并根据您的解决方法解决了,非常感谢您的努力
  • 你太棒了@BalusC!
  • @BalusC 为什么在我的情况下不起作用?存储库github.com/zaknafein83/uploadimage-primefaces-tutorial.git 当我开始时,io 在将 byte[] 内容转换为字符串(Base64)的方法上得到一个空指针异常。如果我添加一个空指针控件,我永远不会得到图像的预览
猜你喜欢
  • 2017-10-31
  • 1970-01-01
  • 2018-04-23
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多