5

我正在将图像上传到服务器,当图像上传时,它应该向我显示上传图像的拇指。缩略图未保存在硬盘上 我使用 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[]任何人都可以告诉我如何用<h:graphicImage>标签显示我的拇指吗?或者任何其他方式。

谢谢 !

4

4 回答 4

9

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

一、更换

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

经过

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

使其生成为

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

src应该即指向一个有效的 URL

然后,创建一个HttpServlet映射在url-patternof上的 a/thumbs/*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 提示可以在这篇文章中找到。

于 2010-02-18T12:24:18.020 回答
3

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

您可以:

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

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

于 2010-02-18T12:14:28.813 回答
1

Richfaces 已经为您抽象了这一点。检查<a4j:mediaOutput>- 您只需将您byte[]的内容写入OutputStream组件提供的内容。

于 2010-02-18T16:59:49.857 回答
0

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

        ImageIcon imageIcon = new ImageIcon(orig);
        Image inImage = imageIcon.getImage();

        int origWidth = inImage.getWidth(null);
        if(origWidth < maxDim) {
            return orig;
        }

        ...
于 2010-05-17T08:40:38.317 回答