簡體   English   中英

為什么graphicImage中的圖像無法完全加載(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)通過將maxExtensionSizemaxTrailerSizeserver.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)編寫了一段代碼,該框架顯示來自同一源的圖像。

我收到相同的錯誤(圖像僅部分顯示)。

由此我得出結論,錯誤必定會發生

  1. 從特定的和/或
  2. 將圖像保存在MongoDB中時。

用於從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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM