2010-02-18 40 views
5

我上傳圖像到服務器,當圖像上傳時,它會顯示上傳圖像的縮略圖。縮略圖不保存在硬盤上我使用InputStream和OutputStream。上傳我是ustig tomahawk。在JSF中創建並顯示縮略圖(字節[])

我的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(); 
    } 
} 

createThumbnail:

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[]可以在任何身體告訴我如何用顯示我的拇指10標籤?或者任何其他方式。

謝謝!

回答

9

這些圖像分別計爲單獨請求。你不能進程 JSF的HTML響應和圖像在一個單一的請求/響應週期。您需要將圖像/拇指存儲在壽命比請求長的數據存儲中的某個位置,例如服務器的本地磁盤文件系統(臨時文件夾?webcontent文件夾?)或數據庫(臨時表?)或會話中。

首先,更換

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

通過

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

,使其獲取生成的

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

(在src應即指向有效的URL

然後,創建這是對/thumbs/*url-pattern映射一個HttpServlet和實施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找到。

3

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。

1

Richfaces已經爲您抽象了。檢查<a4j:mediaOutput> - 您只需將byte[]寫入組件提供的OutputStream

+0

a4j:mediaOutput包含對圖像大小的限制,因爲它將圖像內容編碼爲URL(base64形式)。它僅適用於小圖標 – vim 2013-05-15 10:03:16

0

謝謝ewernli。我已經重用了你的createThumbnail util方法。我添加了這個小小的增強功能,以便在寬度小於規定的maxDim寬度時返回原始圖像。我這樣做是因爲我遇到了一種情況,即該方法返回的圖像比原始圖像大,並填充了黑色像素。

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

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

     ...