【问题标题】:Create and show thumbnail (byte[]) in JSF在 JSF 中创建并显示缩略图 (byte[])
【发布时间】:2011-01-18 07:20:43
【问题描述】:

我正在将图像上传到服务器,当图像上传时,它应该会显示一个已上传图像的拇指。缩略图未保存在硬盘上 我使用 InputStream 和 OutputStream。对于上传,我是 ustig tomahawk。

我的 index.jsp:

<h:form id="uploadForm" enctype="multipart/form-data">
  <t:inputFileUpload id="fileupload" 
    accept="image/*" 
    storage="file"
    value="#{fileUpload.uploadedFile}" 
    styleClass="fileUploadInput"
    required="true" 
    validator="epacient.FileUploadValidator"
    requiredMessage="Obvezna izbira datoteke." 
  />
  <br />
  <h:message for="fileupload" infoStyle="color: green;"
    errorStyle="color: red;" />
  <br />
  <h:commandButton value="Upload" id="fileUploadButton"
    action="#{fileUpload.upload}" />
  <h:message for="uploadForm" style="color: red;" />
  <h:graphicImage value="#{fileUpload.thumb}"
    rendered="#{fileUpload.uploaded}" />

</h:form>

fileUpload.upload 调用函数String preview()

private  String thumb ;
public String preview() throws IOException{
  HttpServletResponse response = (HttpServletResponse)FacesContext
    .getCurrentInstance().getExternalContext().getResponse();
  try {
    FacesContext context = FacesContext.getCurrentInstance();
    Map requestMap = context.getExternalContext().getApplicationMap();
    byte[] bytes = (byte[])(requestMap.get("fileupload_bytes")); 
    // returns byte[]
    byte[] testByte = createThumbnail(bytes, 200);
    // here thumbnail is created
  } catch (Exception ex) {
    ex.printStackTrace();
  }
}

创建缩略图:

public static byte[] createThumbnail( byte[] orig, int maxDim) {
  try {
    ImageIcon imageIcon = new ImageIcon(orig);
    Image inImage = imageIcon.getImage();
    double scale = (double) maxDim / (double) inImage.getWidth(null);

    int scaledW = (int) (scale * inImage.getWidth(null));
    int scaledH = (int) (scale * inImage.getHeight(null));

    BufferedImage outImage = new BufferedImage(scaledW, scaledH, BufferedImage.TYPE_INT_RGB);
    AffineTransform tx = new AffineTransform();

    if (scale < 1.0d) {
      tx.scale(scale, scale);
    }

    Graphics2D g2d = outImage.createGraphics();
    g2d.drawImage(inImage, tx, null);
    g2d.dispose();  

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(outImage, "JPG", baos);
    byte[] bytesOut = baos.toByteArray();

    return bytesOut;
  } catch (IOException e) {
    System.out.println("Erro: " + e.getMessage());
    e.printStackTrace();
  }
  return null;
}

现在我有了我的缩略图,但它在byte[] 中,任何人都可以告诉我如何用&lt;h:graphicImage&gt; 标签显示我的拇指吗?或任何其他方式。

谢谢!

【问题讨论】:

    标签: jsf thumbnails tomahawk


    【解决方案1】:

    每张图片都算作一个单独的请求。您不能在单个请求/响应周期中同时处理(JSF 的)HTML 响应和图像。您需要将图像/拇指存储在数据存储中的某个位置,该数据存储的寿命比请求长,例如服务器的本地磁盘文件系统(临时文件夹?webcontent 文件夹?),或数据库(临时表?),或在会话中。

    首先,替换

    <h:graphicImage value="#{fileUpload.thumb}" ...
    

    通过

    <h:graphicImage value="thumbs/#{fileUpload.thumbId}" ...
    

    使其生成为

    <img src="thumbs/123" ...
    

    src应该指向一个有效的URL

    然后,创建一个映射到/thumbs/*url-patternHttpServlet 并实现doGet(),大致如下:

    Long thumbId = Long.valueOf(request.getPathInfo().substring(1)); // 123
    byte[] thumb = getItFromDiskOrDatabaseOrSessionByThumbId(thumbId);
    String filename = getOriginalFilenameOfUploadedImageOrInventOne();
    
    response.setContentType(getServletContext().getMimeType(filename));
    response.setContentLength(thumb.length);
    response.setHeader("Content-Disposition", "inline; filename=\"" + filename + "\"");
    
    BufferedInputStream input = null;
    BufferedOutputStream output = null;
    
    try {
        input = new BufferedInputStream(new ByteArrayInputStream(thumb));
        output = new BufferedOutputStream(response.getOutputStream());
        byte[] buffer = new byte[8192];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }
    } finally {
        if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
        if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
    }
    

    就是这样。更多 servlet 提示可以在 this article 中找到。

    【讨论】:

      【解决方案2】:

      graphicImage 标记在 HTML 响应中生成一个 img 标记。所以你需要在graphicImage标签的value属性中提供图片的URL,这将对应img标签的src属性。

      您可以:

      • 将缩略图写入filesystem 中可通过HTTP 从外部访问的路径中。然后您可以直接在graphicImagevalue 属性中引用图像,例如/myapp/thumbnail/12345
      • 写一个servlet 在请求时提供图像。 servlet 可以从内存 (HttpSession)、文件系统或数据库中读取图像,也可以每次都生成它。在这种情况下,您需要将参数传递给 servlet,例如/myapp/thumbnail.do?filename=12345

      简而言之,您需要将byte[] 缩略图存储在某处(会话、文件系统、数据库),以便能够直接或通过 servlet 将其作为常规资源提供服务。

      【讨论】:

        【解决方案3】:

        Richfaces 已为您抽象了这一点。检查&lt;a4j:mediaOutput&gt; - 您只需将byte[] 写入组件提供的OutputStream

        【讨论】:

        • a4j:mediaOutput 包含对图像大小的限制,因为它将图像内容编码为 URL(base64 形式)。仅适用于小图标
        【解决方案4】:

        谢谢 ewernli。我重用了您的 createThumbnail util 方法。我添加了这个小增强功能,以便在其宽度小于规定的 maxDim 宽度时返回原始图像。我这样做是因为我遇到了一种情况,该方法返回的图像比原始图像大,并用黑色像素填充。

                ImageIcon imageIcon = new ImageIcon(orig);
                Image inImage = imageIcon.getImage();
        
                int origWidth = inImage.getWidth(null);
                if(origWidth < maxDim) {
                    return orig;
                }
        
                ...
        

        【讨论】:

          猜你喜欢
          • 2019-11-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-01
          • 2017-06-04
          • 2010-11-15
          • 2013-10-22
          • 2011-02-18
          相关资源
          最近更新 更多