问题
I'm uploading image to server and when image is uploaded it should show me a thumb of uploaded image. Thumbnail is not saved on hard disc I use InputStream and OutputStream. For upload i'm ustig tomahawk.
my 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 calls function 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;
}
Now I have my thumbnail but it is in byte[]
can any body tell me how to show my thumb with <h:graphicImage>
tag? Or any other way.
Thank you !
回答1:
The images counts each as a separate request. You cannot process both the HTML response (of JSF) and the image in a single request/response cycle. You need to store the image/thumb somewhere in a datastore which lives longer than a request, e.g. the server's local disk file system (temp folder? webcontent folder?), or a database (temp table?), or in the session.
First, replace
<h:graphicImage value="#{fileUpload.thumb}" ...
by
<h:graphicImage value="thumbs/#{fileUpload.thumbId}" ...
so that it get generated as
<img src="thumbs/123" ...
(the src
should namely point to a valid URL)
Then, create a HttpServlet
which is mapped on an url-pattern
of /thumbs/*
and implement doGet()
roughly like follows:
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) {}
}
That's it. More servlet hints can be found in this article.
回答2:
The graphicImage
tag generates an img
tag in the HTML response. So you need to provide the URL of an image in the value
attribute of the graphicImage
tag, which will correspond to the src
attribute of the img
tag.
You can either:
- Write the thumbnail on the
filesystem
in a path that is accessible form the outside through HTTP. You can then reference the image directly in thevalue
attribute in thegraphicImage
, e.g./myapp/thumbnail/12345
. - Write a
servlet
that serves the image when requested. The servlet can either read the image from memory (HttpSession
), the filesystem, or a database, or generate it each time. In this case you need to pass a parameter to the servlet, e.g./myapp/thumbnail.do?filename=12345
In short, you will need to store your byte[]
thumbnail somewhere (session, filesystem, database), to be able to serve it as regular resource, either directly or through a servlet.
回答3:
Richfaces has abstracted this for you. Check <a4j:mediaOutput> - you just write your byte[]
to an OutputStream
provided by the component.
回答4:
Thanks ewernli. I've reused your createThumbnail util method. I added this little enhancement so that the original image is returned if its width is less than the stipulated maxDim width. I did this because I ran into a situation where the method returned an image that was bigger than the original, padded with black pixels.
ImageIcon imageIcon = new ImageIcon(orig);
Image inImage = imageIcon.getImage();
int origWidth = inImage.getWidth(null);
if(origWidth < maxDim) {
return orig;
}
...
来源:https://stackoverflow.com/questions/2288399/create-and-show-thumbnail-byte-in-jsf