简体   繁体   English

从URL获取PDF并将其推送到客户端浏览器以供下载

[英]get the PDF from a URL and push it to the clients browser for download

I have PDFs mounted on an external server. 我在外部服务器上安装了PDF。 I have to access them in my Java servlet and push them to the clients browser. 我必须在我的Java servlet中访问它们并将它们推送到客户端浏览器。 The PDF should get downloaded directly or it may open a 'SAVE or OPEN' dialog window. PDF应该直接下载,也可以打开“保存或打开”对话框窗口。 This is what i am trying in my code but it could not do much. 这就是我在我的代码中尝试但它无法做多少。

URL url = new URL("http://www01/manuals/zseries.pdf");
ByteArrayOutputStream bais = new ByteArrayOutputStream();
InputStream in = url.openStream();

int FILE_CHUNK_SIZE = 1024 * 4;
byte[] chunk = new byte[FILE_CHUNK_SIZE]; 
int n =0;
 while ( (n = in.read(chunk)) != -1 ) {
        bais.write(chunk, 0, n);
  }

I have tried many ways to do this but could not succeed. 我已经尝试了很多方法来做到这一点,但无法成功。 I welcome if you have any good method to do this! 如果你有任何好的方法可以做到这一点我欢迎!

When you read the data, you get it inside your program memory, which is on the server side. 当您读取数据时,可以将其放在程序存储器中,该存储器位于服务器端。 To get it to the user's browser, you have to also write everything that you have read. 要将其发送到用户的浏览器,您还必须编写已阅读的所有内容。

Before you start writing, though, you should give some appropriate headers. 但是,在开始编写之前,您应该提供一些合适的标题。

  • Indicate that you are sending over a PDF file, by setting the mime type 通过设置mime类型,指示您通过PDF文件发送
  • Set the content length. 设置内容长度。
  • Indicate that the file is intended for download rather than showing inside the browser. 指示该文件旨在下载而不是在浏览器中显示。

To set the mime type, use 要设置mime类型,请使用

response.setContentType("application/pdf");

To set the content length, assuming it's the same content length that you get from the URL, use: 要设置内容长度,假设它与从URL获得的内容长度相同,请使用:

HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.connect();
if ( connection.getResponseCode() == 200 ) {
    int contentLength = connection.getContentLength();
    response.setContentLength( contentLength );

To indicate that you want the file to be downloaded, use: 要指示您要下载文件,请使用:

    response.setHeader( "Content-Disposition", "attachment; filename=\"zseries.pdf\"";

(Take care to change the file name to whatever you want the user to see in the save dialog box) (注意将文件名更改为您希望用户在保存对话框中看到的任何内容)

Finally, get the input stream from the URLConnection you just opened, get the servlet's response output stream, and start reading from one and writing to the other: 最后,从刚刚打开的URLConnection获取输入流,获取servlet的响应输出流,然后从一个读取并写入另一个:

    InputStream pdfSource = connection.getInputStream();
    OutputStream pdfTarget = response.getOutputStream();

    int FILE_CHUNK_SIZE = 1024 * 4;
    byte[] chunk = new byte[FILE_CHUNK_SIZE]; 
    int n =0;
    while ( (n = pdfSource.read(chunk)) != -1 ) {
        pdfTarget.write(chunk, 0, n);
    }
} // End of if

Remember to use try/catch around this, because most of these methods throw IOException , timeout exceptions etc., and to finally close both streams. 请记住在此周围使用try / catch,因为大多数这些方法会抛出IOException ,超时异常等,并最终关闭两个流。 Also remember to do something meaningful (like give an error output) in case the response was not 200. 还记得在响应不是200的情况下做一些有意义的事情(例如给出错误输出)。

You could transfer the byte array to the client, then use Itext to "stamp" the pdf in a new file. 您可以将字节数组传输到客户端,然后使用Itext在新文件中“标记”pdf。 After that use java.awt.Desktop to lauch the file. 之后使用java.awt.Desktop来实现文件。

public static void lauchPdf(byte[] bytes, String fileName) throws DocumentException, IOException{
    PdfReader reader = new PdfReader(bytes);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(fileName));
    stamper.close();
    Desktop dt = Desktop.getDesktop();
    dt.browse(getFileURI(fileName));
}

You don't need to push anything (hope you really don't, because actually you can't). 你不需要推动任何东西(希望你真的没有,因为实际上你不能)。 From the perspective of the browser making the request, you could get the PDF from the database, generate it on the fly or read it from the filesystem (which is your case). 从发出请求的浏览器的角度来看,您可以从数据库中获取PDF,动态生成PDF或从文件系统中读取它(这是您的情况)。 So, let's say you have this in your HTML: 所以,假设你在HTML中有这个:

<a href="/dl/www01/manuals/zseries.pdf">DOWNLOAD FILE</a>

you need to register a servlet for /dl/* and implement the doGet(req, resp) like this: 你需要为/dl/*注册一个servlet并实现doGet(req, resp)如下所示:

public void doGet(
              HttpServletRequest req
            , HttpServletResponse resp
) throws IOException { 

  resp.setContentType("application/pdf");
  response.setHeader("Content-Disposition",
          "attachment; filename=\"" + suggestFilename(req) + "\"");

  // Then copy the stream, for example using IOUtils.copy ...
  // lookup the URL from the bits after /dl/*
  URL url = getURLFromRequest(req);
  InputStream in = url.openConnection().getInputStream();
  IOUtils.copy(in, resp.getOutputStream());
  fin.close();
}

IOUtils is from Apache Commons IO (or just write your own while loop) IOUtils来自Apache Commons IO(或者只是编写自己的while循环)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM