java 无法使用 HttpServletResponse 下载文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10083611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 23:32:09  来源:igfitidea点击:

Cannot download a file using HttpServletResponse

javafile-ioms-wordnullpointerexception

提问by Sunmit Girme

I want to download a MS Word 2003 document that I am creating with the content myStringin it. I have used the following code:

我想下载我正在创建的包含其中内容的 MS Word 2003 文档myString。我使用了以下代码:

BufferedReader reader = new BufferedReader(new FileReader(templatePathFilename));
HttpServletResponse response = new MyHttpServletResponse();
response.setContentType ("application/msword"); 
response.setHeader ("Content-Disposition", "attachment; filename=\""+outgoingFileName); 
ServletOutputStream myOut = response.getOutputStream();
myOut.write(myString.getBytes());
myOut.flush();
myOut.close();

But the line myOut.write(myString.getBytes())gives a NullPointerException. MyHttpServletResponseis a class that eclipse has produced by default when I quick fix the error generated. Do I need to modify that class? Can anyone please help!

但是该行myOut.write(myString.getBytes())给出了 NullPointerException。 MyHttpServletResponse是 Eclipse 在我快速修复生成的错误时默认生成的类。我需要修改那个类吗?任何人都可以请帮忙!

EDIT: The actual code i am working on is as below:

编辑:我正在处理的实际代码如下:

BufferedReader reader = new BufferedReader(new FileReader(templatePathFilename));
String outgoingFileName = outputPathFilename;
response.setContentType("application/msword"); 
response.setHeader("Content-Disposition", "attachment; filename="+outgoingFileName);
OutputStream myOut = response.getOutputStream();
try {
String thisLine;
while ((thisLine = reader.readLine()) != null) {
    if(thisLine.contains("##"))
    {
    for (java.util.Enumeration e = FrontSheetMap.keys(); e.hasMoreElements();{
     String name = (String) e.nextElement();
     String value = FrontSheetMap.get(name).toString();
     thisLine= thisLine.replaceAll("##" + name.toUpperCase() + "##", value);
    }
   }
   myOut.write(thisLine);
   myOut.write("\n");
  }
  myOut.flush();
}catch(Exception e){}

The while loop replaces the placeholders in the input file with required values and the new content in thisLineis to be written on the output file. I need a download option which pops up on clicking the link which executes this code.

while 循环将输入文件中的占位符替换为所需的值,并将输入的新内容thisLine写入输出文件。我需要一个下载选项,它会在单击执行此代码的链接时弹出。

采纳答案by Santosh

As you mentioned MyHttpServletResponseis a class that eclipse has produced by default when I quick fix the error generated, that seems to be the problem.

正如您提到MyHttpServletResponse的,当我快速修复生成的错误时,eclipse 默认生成的一个类,这似乎是问题所在。

Your code should be inside some servlet/JSPand the HttpServletResponse object should be taken from the container (which is passed to service/doGet/doPost methods).

您的代码应该在某个 servlet/JSP 内,并且应该从容器中获取 HttpServletResponse 对象(它被传递给 service/doGet/doPost 方法)。

What you are using is a default/dummy implementationof HttpServletResponsewhich gives response.getOutputStream();as null. If you use the container provided objects, your problem will be solved.

什么您使用的是默认/虚拟实现HttpServletResponse,其提供了response.getOutputStream();为空。如果您使用容器提供的对象,您的问题将得到解决。

回答by Sourav Bairagi

If you are using a Java EE platform to perform the download operation to occur then the safest way is to do it through a servlet. A Sample Download servlet should Look like below,

如果您使用 Java EE 平台来执行下载操作,那么最安全的方法是通过 servlet 来完成。示例下载 servlet 应如下所示,

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.*; 
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class DownloadFile extends HttpServlet{
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();

        // Prepare the File Read.
        String fileName = request.getParameter("fileName");
        fileName = fileName.substring(fileName.lastIndexOf("\") + 1, fileName.length());
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
        String filePath = "C:/temp/" + fileName;
        FileInputStream fileToDownload = new FileInputStream(filePath);

        // Prepare the Headers.
        if (extension.equalsIgnoreCase("txt")) {
            response.setContentType("text/html");
        } else if (extension.equalsIgnoreCase("doc")) {
            response.setContentType("application/msword");
        } else if (extension.equalsIgnoreCase("pdf")) {
            response.setContentType("application/pdf");
        } else if (extension.equalsIgnoreCase("jpg")) {
            response.setContentType("image/jpeg");
        } else if (extension.equalsIgnoreCase("jpeg")) {
            response.setContentType("image/jpeg");
        }
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        response.setContentLength(fileToDownload.available());

        // Download the file.
        int c;
        while ((c = fileToDownload.read()) != -1) {
            out.write(c);
        }
        out.flush();
        out.close();
        fileToDownload.close();
    }
}

回答by Sajjad Ahmed Paracha

Add your filename to the header like below (Filename should include the extention like if you have a word document named abc the file name should be abc.doc "i.e. with extention"), no need to check the extension and then set the content type

将您的文件名添加到如下标题中(文件名应包括扩展名,如果您有一个名为 abc 的 word 文档,文件名应为 abc.doc“即带有扩展名”),无需检查扩展名,然后设置内容类型

httpServletResponse.addHeader("Content-Disposition", "attachment; filename=" + fileName);

httpServletResponse.addHeader("Content-Disposition", "attachment; filename=" + fileName);

The remaining code remains the same and try it now , you should be able to see a popup asking your permission to open a this word document.

剩下的代码保持不变,现在试试吧,你应该能够看到一个弹出窗口,询问你是否允许打开这个 word 文档。

Below is a code snipet which is working for me

下面是一个对我有用的代码片段

        OutputStream outputStream=httpServletResponse.getOutputStream();
        httpServletResponse.addHeader("Content-Disposition", "attachment; filename="
                  + fileName);



        //**Take the data from input stream and write it on outputstream
        try{
            IOUtils.copy(documentumClientSession.getFile(fileName,dbpNum), outputStream);
        }catch(Exception exp){
            exp.printStackTrace();
        }

I am using apache commons api that's why you can see org.apache.commons.io.IOUtils the class being used but you can replace it with your own loop in the code.

我正在使用 apache commons api,这就是为什么您可以看到 org.apache.commons.io.IOUtils 正在使用的类,但您可以在代码中用您自己的循环替换它。