![](/img/trans.png)
[英]How to load an image from a directory using graphicImage in Primefaces?
[英]Why does an image in graphicImage not load fully (PrimeFaces mobile)?
我有一個使用PrimeFaces Mobile顯示圖像的應用程序。
有時但並非總是如此,圖像無法完全顯示-僅頂部顯示。
具有該圖像的頁面的XHTML代碼如下所示:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:pm="http://primefaces.org/mobile">
<f:view renderKitId="PRIMEFACES_MOBILE"/>
<h:head>
</h:head>
<f:event listener="#{main.loadFirstImage}" type="preRenderView" />
<h:body id="body">
<pm:page id="page">
<pm:header title="myapp">
</pm:header>
<pm:content id="content">
<h:form>
<p:graphicImage id="image" rendered="false" value="#{main.currentImage()}"
cache="false">
</p:graphicImage>
[...]
</h:form>
</pm:content>
<pm:footer title="m.myapp.com"></pm:footer>
</pm:page>
</h:body>
</html>
並且main
bean具有以下代碼:
@ManagedBean(name = "main")
@SessionScoped
public class MainView {
private byte[] currentImageData;
private byte[] productId;
private byte[] imageId;
public void loadFirstImage()
{
// This method initializes currentImageData
fetchNextImage();
}
[...]
public StreamedContent currentImage()
{
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
else {
return new DefaultStreamedContent(new ByteArrayInputStream(currentImageData));
}
}
[...]
}
如何解決此錯誤?
更新1(03.11.2014 23:21 MSK):
我已經嘗試按照以下方法修復錯誤:
1)為該Primefaces頁面的所有元素禁用緩存。
2)通過將maxExtensionSize
和maxTrailerSize
( server.xml
)設置為-1
來禁用響應分塊。
3)使用以下doFilter
添加過濾doFilter
:
@Override
public void doFilter(final ServletRequest aServletRequest,
final ServletResponse aServletResponse,
final FilterChain aFilterChain) throws IOException, ServletException {
System.out.println("aServletRequest instanceof HttpServletRequest: " +
(aServletRequest instanceof HttpServletRequest));
if (aServletRequest instanceof HttpServletRequest)
{
final HttpServletRequest request = (HttpServletRequest) aServletRequest;
final String requestURI = request.getRequestURI().toLowerCase();
if (!requestURI.endsWith("/javax.faces.resource/dynamiccontent.properties"))
{
aFilterChain.doFilter(aServletRequest, aServletResponse);
}
}
}
4)將currentImage
方法更改為
public StreamedContent currentImage()
{
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
}
else {
String mimeType = null;
if (imageFileName.toLowerCase().endsWith(".png"))
{
mimeType = "image/png";
}
else if (imageFileName.toLowerCase().endsWith(".jpeg") || imageFileName.toLowerCase().endsWith(".jpg"))
{
mimeType = "image/jpeg";
}
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
return new DefaultStreamedContent(new ByteArrayInputStream(currentImageData), mimeType);
}
}
但這仍然行不通。 我在另一個Web應用程序中使用了不同的框架(Vaadin)編寫了一段代碼,該框架顯示來自同一源的圖像。
我收到相同的錯誤(圖像僅部分顯示)。
由此我得出結論,錯誤必定會發生
用於從URL檢索圖像的代碼
如果在讀取圖像期間發生錯誤,則按以下方法發生:
protected Binary readImage(final String viewItemURL) {
InputStream inputStream = null;
Binary image = null;
try
{
inputStream = new URL(viewItemURL).openStream();;
byte bytes[] = new byte[inputStream.available()];
inputStream.read(bytes);
image = new Binary(bytes);
}
catch (final IOException exception)
{
LOGGER.error("", exception);
}
finally
{
IOUtils.closeQuietly(inputStream);
}
return image;
}
viewItemURL
是圖像的URL。
在MongoDB中保存圖像的代碼
如果問題在於將圖像保存在數據庫中,則將通過以下方法發生:
protected void saveProductImages(final byte[] aNewProductId, final List<String> aPictureUrls,
final IMongoPersistenceState aPersistenceState) {
final DB db = aPersistenceState.getDb();
final DBCollection productImagesColl = db.getCollection(
MyAppPersistenceAction.COLLECTION_USER_PRODUCT_IMAGES);
for (final String curPictureUrl : aPictureUrls)
{
final Binary imageData = readImage(curPictureUrl);
final Map<String,Object> map = new HashMap<String, Object>();
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_CREATOR_EMAIL, CREATOR_EMAIL);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_PRODUCT_ID, aNewProductId);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_DATA, imageData);
final String fileName = extractFileName(curPictureUrl);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_FILE_NAME, fileName);
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_MIME_TYPE, getMimeType(fileName));
map.put(FIELD_COLLECTION_USER_PRODUCT_IMAGES_IS_DELETED, Boolean.FALSE);
productImagesColl.insert(WriteConcern.SAFE, createRecordObject(map));
}
}
您的readImage()
方法有一個主要錯誤:
byte bytes[] = new byte[inputStream.available()];
InputStream#available()
不會執行您認為的操作。 它不會返回總的內容長度,這是其余代碼所期望的。 它返回可讀取的字節數,而不會阻塞所有其他線程(即,當前已放入硬件緩沖區的字節)。 這完全解釋了為什么只顯示圖像的那一部分。
無需羞愧。 實際上,所有Java入門者都會犯同樣的錯誤 。 完全讀取InputStream
的正確方法是,對其調用任何 read()
方法 ,直到返回-1
表示EOF(文件末尾)為止。 您可以在以下相關問題中找到大量示例和實用程序庫快捷方式: 將InputStream轉換為Java中的字節數組 。
下面是一個完整的重寫readImage()
方法做正確的事,利用IOUtils
,你似乎已經在你的手(和Java 7的嘗試-以資源與AutoCloseable
):
protected Binary readImage(final String viewItemURL) {
try (InputStream inputStream = new URL(viewItemURL).openStream()) {
return new Binary(IOUtils.toByteArray(inputStream));
}
catch (final IOException exception) {
LOGGER.error("", exception);
return null;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.