如何使用servlet从服务器读取pdf文件? [英] how to read pdf file from server using servlet?

查看:237
本文介绍了如何使用servlet从服务器读取pdf文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这里,我正在尝试使用Java Servlet从服务器读取pdf文件.下面的代码,如果文件存在,我将获取文件路径,然后尝试读取文件,但是文件无法打开?

here i'm trying to read pdf file from server using java servlet. the below code i'm getting file path if file exists and then try to read file but,file does not open ?

 String filePath = dirName;
            String fileName = si + "_" + dnldFilename;
            FileInputStream fileToDownload = new FileInputStream(filePath.concat(fileName);
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            response.setContentLength(fileToDownload.available());
            int c;
            while ((c = fileToDownload.read()) != -1) {
                response.getOutputStream().write(c);
            }
            response.getOutputStream().flush();
            response.getOutputStream().close();
            fileToDownload.close();

推荐答案

错误在这里:

response.setContentLength(fileToDownload.available());

InputStream#available() 不能满足您的要求(和普通的Java入门者).它不会返回响应标头表示的总内容长度.它返回可读取的字节数,而不会阻塞所有其他线程(即当前已放入硬件缓冲区的字节).如果它小于实际文件大小,则客户端可以简单地停止读取响应的其余部分.换句话说,客户只得到了PDF文件的一部分,因为您告诉客户所需的部分正好是给定的长度.

The InputStream#available() doesn't do what you (and the average Java starter) think. It doesn't return the total content length which is what the response header represents. It returns the amount of bytes available for reading without blocking all other threads (i.e. bytes which are currently already put in hardware buffer). If this is lower than the actual file size, then the client may simply stop reading the remainder of the response. In other words, the client got only a part of the PDF file, because you told the client that the desired part is of exactly the given length.

您需要构建一个普通的 java.io.File 并通过

You need to construct a normal java.io.File and get the file size via File#length().

这是一个完整的重写,也减少了更多的旧版Java IO样板.假设您至少使用Java 7(因为Java 6自2013年以来就处于停产状态,所以没人会认为您仍然是Java 6才两年后):

Here's a complete rewrite, reducing further legacy Java IO boilerplate too. This assumes you're on at least Java 7 (as Java 6 is EOL since 2013, no one would expect you're 2 years after date still at Java 6 anyway):

File file = new File(filePath, fileName);
response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());

就是这样.请注意,上述代码段也可用于所有其他类型的文件.您可以通过web.xml中的<mime-mapping>条目来管理未知的内容类型.

That's it. Do note that the above code snippet is this way reusable for all other kinds of files too. You can manage unknown content types via <mime-mapping> entries in web.xml.

还请注意,我正在将内容长度转换为字符串,因为setContentLength()仅接受int,而File#length()返回long,如果文件大于2GB,该操作将失败.如果您已经在使用Servlet 3.1(Tomcat 8等),请使用新的

Also note that I'm converting the content length to string as the setContentLength() takes only an int and File#length() returns long, which would fail if the file is larger than 2GB. In case you're on Servlet 3.1 (Tomcat 8, etc) already, make use of new setContentLengthLong() method.

response.setContentLengthLong(file.length());

另请参见:

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆