1

最后,我的最终目标是:

  • 从 URL 读取(这个问题是关于什么的)
  • 将检索到的 [PDF] 内容保存到数据库中的 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 阅读器客户端(如 Adob​​e 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 回答