0

Google Cloud Storage に保存されているファイルからバイトを読み取って HTTP POST リクエストで送信しようとしていますが、大きなファイルはこの例外が発生します。コードは小さなファイルで動作します:

例外は次の行でスローされます。

writer.write(blobstoreService.fetchData(new BlobKey(video.getBlobkey()), start, end));

これは私のコードです:

    URLConnection connection = new URL("http://myurl.com/").openConnection();
    //set time out to infinite
    connection.setConnectTimeout(0);
    connection.setDoOutput(true);
    connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    BufferedOutputStream writer = null;
    OutputStream output = connection.getOutputStream();
    writer = new BufferedOutputStream(output); // true = autoFlush, important!

    //........

    BlobInfoFactory blobInfoFactory = new BlobInfoFactory();
    BlobInfo blobInfo = blobInfoFactory.loadBlobInfo(new BlobKey(video.getBlobkey()));
    Long blobSize = blobInfo.getSize();
    //max read on fetch
    long maxReadFetch = 1015807;
    //read the file in one time temporary
    long i = 0;
    long start = 0;
    long end = 0;
    while(i < blobSize) {
        start = i;
        end = i + maxReadFetch;
        //determine end
        if(end > blobSize) {
            end = blobSize;
        } else {
            end--;
        }
        writer.write(blobstoreService.fetchData(new BlobKey(video.getBlobkey()), start, end));

        i += maxReadFetch;
    }
    writer.flush(); // Important! Output cannot be closed. Close of writer will close output as well.
} finally {
    if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}

スタックトレース:

サーブレット java.lang.OutOfMemoryError からのキャッチされない例外: com.google.apphosting の java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:111) の java.util.Arrays.copyOf(Arrays.java:2961) の Java ヒープ スペース。 utils.security.urlfetch.URLFetchServiceStreamHandler$Connection$BufferingOutputStream.write(URLFetchServiceStreamHandler.java:460) で java.io.BufferedOutputStream.write(BufferedOutputStream.java:122) で java.io.FilterOutputStream.write(FilterOutputStream.java:97) でcontroller.CtrlWistia.upload(CtrlWistia.java:200) で controller.CtrlWistia.add(CtrlWistia.java:126) で controller.CtrlWistia.ajax(CtrlWistia.java:79) で controller.CtrlAjax.main(CtrlAjax.java: 66) vidaao.AjaxServlet.doPost(AjaxServlet.java:37) で javax.servlet.http.HttpServlet.service(HttpServlet.java:637) で javax.servlet.http.HttpServlet.service(HttpServlet.java:717) で org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) で org.mortbay.jetty.servlet.ServletHandler$CachedChain org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176) の .doFilter(ServletHandler.java:1166) org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145) の) org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92) で org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:394) で org.mortbay.jetty. servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) (com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125))org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler. java:1157) com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) で org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) で org.mortbay .jetty.servlet.ServletHandler.handle(ServletHandler.java:388) org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java) :182) org.mortbay.jetty.webapp.WebAppContext の org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) で。ハンドル (WebAppContext.java:418) で com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:266) で org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)

4

1 に答える 1

1

一度に読み取るのは 1MB 未満ですが、そのデータを OutputStream に書き込んでいることに注意してください。このデータは、リクエストを送信するまでメモリに保持されます。

ドキュメントによると:

URLConnection の App Engine の実装は、リモート ホストとの永続的な接続を維持しません。アプリが要求データを設定するか出力ストリームに書き込むと、要求データはメモリに保持されます。入力ストリームの取得 (または connect() メソッドの呼び出し) など、アプリが応答に関するデータにアクセスすると、App Engine は要求データを使用して URL Fetch サービスを呼び出し、応答を取得し、接続を閉じて応答データを返します。 .

于 2013-03-05T18:10:07.740 に答える