从特定文件夹下载文件的Servlet?

6

我是一名JAVA技术新手,尤其是Servlets方面。我需要制作一个Web应用程序项目,该项目具有将文件上传和从服务器(Tomcat)下载文件的功能。我已经有了一个可正常工作的上传servlet。

我还找到了一个在互联网上发现的下载servlet。但问题是,这个servlet只允许下载特定文件,并且该特定文件的路径在servlet中给出。我需要让客户端查看我的上传文件夹的全部内容,并从该文件夹选择要下载的文件。

下载servlet的代码如下:

import java.io.DataInputStream; 
import java.io.File; 
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletContext; 
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;



 public class DownloadServlet extends javax.servlet.http.HttpServlet implements
            javax.servlet.Servlet {
        static final long serialVersionUID = 1L;
        private static final int BUFSIZE = 4096;
        private String filePath;`

public void init() {
    // the file data.xls is under web application folder

    filePath = getServletContext().getRealPath("")  + File.separator;// + "data.xls";
}

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    File file = new File(filePath);
    int length   = 0;
    ServletOutputStream outStream = response.getOutputStream();
    ServletContext context  = getServletConfig().getServletContext();
    String mimetype = context.getMimeType(filePath);

    // sets response content type
    if (mimetype == null) {
        mimetype = "application/octet-stream";
    }
    response.setContentType(mimetype);
    response.setContentLength((int)file.length());
    String fileName = (new File(filePath)).getName();

    // sets HTTP header
    response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

    byte[] byteBuffer = new byte[BUFSIZE];
    DataInputStream in = new DataInputStream(new FileInputStream(file));

    // reads the file's bytes and writes them to the response stream
    while ((in != null) && ((length = in.read(byteBuffer)) != -1))
    {
        outStream.write(byteBuffer,0,length);
    }

    in.close();
    outStream.close();
}
}

这个 JSP 页面是这样的:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Download Servlet Test</title>
</head>
<body>
Click on the link to download: <a href="DownloadServlet">Download Link</a>
</body>
</html>

我搜索了很多Servlets,但它们都像这样...它们只允许下载特定的文件。 有人能帮忙吗? 非常感谢!


你尝试了些什么?你修改过你下载的代码吗?你做了哪些更改?哪些东西起作用了?哪些没有?你除了寻找可下载的完整解决方案之外,还进行了其他研究吗?仅从互联网上抄袭代码是不够的,有时你必须自己动手。 - Adrian
@Adrian 谢谢您的回复。正如我所说,上面的代码仅适用于在Servlet中给定路径下载单个文件。在此示例中,在init()函数中。我尝试将路径作为字符串提供给filePath属性。例如:filepath = "C://Apache//Application//data//",但是我收到了一个错误:拒绝访问。我尝试了其他方法:使用文件属性和listFiles方法在我的JSP中列出文件夹内容的列表,然后我写了'<a href="<%=file.getAbsolutePath()%>" target="_blank"><br> <%=file.getName() %>',但这只在I.E.中使用“另存为”才有效。 - AdiCrainic
@user2236267 尝试使用不同的路径,例如 C:\external\path。另外,请确保您的用户拥有足够的权限来写入该文件夹。我没有包含这些信息,因为我假设您已经知道它。 - Luiggi Mendoza
我对JAVA编程非常新手。我尝试了很多方法来解决我的问题,但是我没有找到任何解决方案。我会继续努力,如果我找到了任何解决方案,我会在这里发布。 - AdiCrainic
3个回答

6

由于您正在处理doGet方法中的数据,因此可以向servlet传递参数,其中指示您要下载的文件的名称。为此,您应假定文件名存在于基本路径中。 代码可能如下所示:

HTML

<body>
    Click on the link to download:
    <a href="DownloadServlet?fileName=data.xls">Download Link</a>
</body>

Java Servlet 代码:

protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
    //retrieving the parameter by its name
    String fileName = request.getParameter("fileName"); //this will return `data.xls`
    //using the File(parent, child) constructor for File class
    File file = new File(filePath, fileName);
    //verify if the file exists
    if (file.exists()) {
        //move the code to download your file inside here...

    } else {
        //handle a response to do nothing
    }
}

请注意,由于代码现在使用File(String parent, String child)构造函数,因此您的filePath不应再包含分隔符(这将由Java处理):
public void init() {
    // the file data.xls is under web application folder
    filePath = getServletContext().getRealPath("");
}

@user2236267 试一试。如果它满足您的需求,请在声望下方标记复选框以将帖子标记为答案。 - Luiggi Mendoza
我是Stack Overflow的新手,需要一些时间来适应。我试图给你的答案点赞,但它告诉我我需要15个声望。我想回复我的新代码,但它告诉我我的评论太长了。 - AdiCrainic
我不明白客户端如何看到我上传文件夹中的全部内容。那里有很多文件,比如test.txt、test.pdf、image.jpg等。我希望用户可以选择要下载哪些文件,而不仅仅是在HTML页面中作为参数给出一个文件。 - AdiCrainic
@user2236267 这是一个全新的需求,应该在一个新问题中进行处理。确保在发布问题之前尝试一些东西。解决您的要求的一个想法是拥有一个servlet,它将设置一个request属性,其中包含文件夹中文件的名称的 List<String>。为了更好地理解,可以参考 StackOverflow Servlet wiki - Luiggi Mendoza
非常感谢您的帮助,Luiggi Mendoza。祝您有美好的一天! - AdiCrainic
显示剩余3条评论

2

你可以这样做

     public void doGet(HttpServletRequest req, HttpServletResponse res){
     res.setContentType("text/html);
      PrintWriter out=response.getWriter();
      String fileName="home.txt";
      String filePath="d:\\";
    response.setContentType("APPLICATION/OCTET-STREAM");
    response.setHeader("Content-Disposition","attachment;fileName=\""+fileName+"\"");
    int i;
    FileInputStream file=new FileInputStream(filePath +fileName);
    while((i=file.read()) !=-1){
      out.write(i);
   }
    file.close();
   out.close();
}

0
  // get MIME type of the file
    String mimeType = context.getMimeType(fullPath);
    if (mimeType == null) {
        // set to binary type if MIME mapping not found
        mimeType = "application/octet-stream";
    }
    System.out.println("MIME type: " + mimeType);

    // set content attributes for the response
    response.setContentType(mimeType);
    response.setContentLength((int) downloadFile.length());

以下是更详细的内容以及如何改进的问题: https://stackoverflow.com/questions/41914092/how-change-servlet-which-download-single-file-but-can-folderfew-files-in-fold


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接