1

最後に、私の最終的な目標は次のとおりです。

  • URL から読み取る (この質問の内容)
  • 取得した [PDF] コンテンツを DB の BLOB フィールドに保存します (既に特定されています)。
  • BLOB フィールドから読み取り、そのコンテンツをメールに添付します
  • ファイルシステムにアクセスする必要はありません

次のメソッドの目的はbyte[]、電子メールの添付ファイルとしてダウンストリームで使用できる を取得することです (ディスクへの書き込みを避けるため)。

public byte[] retrievePDF() {

         HttpClient httpClient = new HttpClient();

         GetMethod httpGet = new GetMethod("http://website/document.pdf");
         httpClient.executeMethod(httpGet);
         InputStream is = httpGet.getResponseBodyAsStream();

         byte[] byteArray = new byte[(int) httpGet.getResponseContentLength()];

         is.read(byteArray, 0, byteArray.length);

        return byteArray;
}

特定の PDF の場合、このgetResponseContentLength()メソッドは長さとして 101,689 を返します。奇妙な点は、ブレークポイントを設定してbyteArray変数に問い合わせると、101,689 バイトの要素があるのに、バイト #3744 の後、配列の残りのバイトがすべてゼロ ( 0) になることです。 結果の PDF は、Adobe Reader などの PDF リーダー クライアントでは読み取ることができません。

なぜそれが起こるのでしょうか?

この同じ PDF をブラウザー経由で取得してディスクに保存するか、次のような方法 (この StackOverflow 投稿への回答に基づいてパターン化したもの) を使用すると、読み取り可能な PDF が生成されます。

public void retrievePDF() {
    FileOutputStream fos = null;
    URL url;
    ReadableByteChannel rbc = null;

    url = new URL("http://website/document.pdf");

    DataSource urlDataSource = new URLDataSource(url);

    /* Open a connection, then set appropriate time-out values */
    URLConnection conn = url.openConnection();
    conn.setConnectTimeout(120000);
    conn.setReadTimeout(120000);

    rbc = Channels.newChannel(conn.getInputStream());

    String filePath = "C:\\temp\\";
    String fileName = "testing1234.pdf";
    String tempFileName = filePath + fileName;

    fos = new FileOutputStream(tempFileName);
    fos.getChannel().transferFrom(rbc, 0, 1 << 24);
    fos.flush();

    /* Clean-up everything */
    fos.close();
    rbc.close();
}

どちらのアプローチでも、Windows で右クリック > プロパティ...を実行すると、結果の PDF のサイズは 101,689 バイトになります。

バイト配列が本質的に途中で「停止」するのはなぜですか?

4

3 に答える 3

5

InputStream.readバイトまで読み取りbyteArray.lengthますが、正確にはそれほど多くは読み取れない場合があります。読み取ったバイト数を返します。次のように、データを完全に読み取るために繰り返し呼び出す必要があります。

int bytesRead = 0;
while (true) {
    int n = is.read(byteArray, bytesRead, byteArray.length);
    if (n == -1) break;
    bytesRead += n;
}
于 2012-10-03T22:37:29.150 に答える
0

の戻り値を確認してくださいInputStream.read。一気に読むわけではありません。ループを書く必要があります。または、さらに良いことに、Apache Commons IO を使用してストリームをコピーします。

于 2012-10-03T22:36:19.123 に答える
0

101689 = 2^16 + 36153なので、バッファ サイズには 16 ビットの制限があるように見えます。36153 と 3744 の違いは、ヘッダー部分が非常に小さい 1K 程度のバッファーで読み取られ、既にいくつかのバイトが含まれていることに起因する可能性があります。

于 2012-10-03T23:29:26.370 に答える