Java实现文件上传和下载的方法详解

yizhihongxing

Java实现文件上传和下载的方法详解

文件上传

文件上传是通过HTTP协议中的POST方法进行实现的。在Java中,常见的实现方式有两种:

1. 使用Servlet API

Servlet API 提供了实现文件上传的类 javax.servlet.http.Part。我们可以通过 request.getParts() 方法来获取所有上传的文件数据,然后进行处理。

@WebServlet("/upload")
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, // 2MB
                 maxFileSize = 1024 * 1024 * 10, // 10MB
                 maxRequestSize = 1024 * 1024 * 50) // 50MB
public class FileUploadServlet extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 获取上传的文件数据
    Collection<Part> parts = request.getParts();

    for (Part part : parts) {
      String fileName = extractFileName(part);
      InputStream partInputStream = part.getInputStream();

      // 可以将文件数据写入到磁盘中
    }
  }

  // 根据Part获取原始文件名
  private String extractFileName(final Part part) {
    final String partHeader = part.getHeader("content-disposition");
    String[] parts = partHeader.split(";");
    for (String partItem : parts) {
      if (partItem.trim().startsWith("filename")) {
        return partItem.substring(partItem.indexOf('=') + 1).trim()
                        .replace("\"", "");
      }
    }
    return "";
  }
}

上述代码中通过 request.getParts() 获取了所有上传的文件数据,然后遍历每个文件,从每个文件中获取文件名和数据流。可以将数据流写入到磁盘中,也可以将其存储到数据库。

需要注意的是,在实际应用中,我们应该对上传文件的类型、大小等进行限制和校验,避免上传恶意文件和文件过大导致磁盘空间不足等问题。示例中使用 @MultipartConfig 注解对文件大小和请求大小进行了限制。

2. 使用第三方库

在实际开发中,往往会使用一些第三方库来简化文件上传的实现。常见的库有 Apache Commons FileUpload 和 Spring Framework。

以 Apache Commons FileUpload 为例,代码如下:

public class FileUploadHandler extends HttpServlet {

  private static final long serialVersionUID = 1L;

  private static final String TEMP_DIRECTORY = "C:/temp";
  private static final int MAX_UPLOAD_SIZE = 1024 * 1024 * 10; // 10MB
  private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
  private static final int FILE_SIZE_THRESHOLD = 0;

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    DiskFileItemFactory factory = new DiskFileItemFactory();
    factory.setSizeThreshold(FILE_SIZE_THRESHOLD);
    factory.setRepository(new File(TEMP_DIRECTORY));
    ServletFileUpload upload = new ServletFileUpload(factory);
    upload.setFileSizeMax(MAX_UPLOAD_SIZE);
    upload.setSizeMax(MAX_REQUEST_SIZE);

    try {
      List<FileItem> items = upload.parseRequest(request);
      if (items != null) {
        for (FileItem item : items) {
          if (!item.isFormField()) {
            String fileName = item.getName();
            InputStream is = item.getInputStream();

            // 可以将文件数据写入到磁盘中或存储到数据库
          }
        }
      }
    } catch(FileUploadException e) {
      // 处理文件上传异常
    }
  }
}

在上面的示例代码中,Apache Commons FileUpload 将文件上传的过程封装在了 ServletFileUploadFileItem 类中,使得文件上传变得十分简便。需要注意的是,除了第一种方式中的检查之外,Apache Commons FileUpload 可以对上传的文件类型、大小等进行自动检查和处理。

文件下载

文件下载是通过向客户端发送 HTTP 响应实现的。在 Java 中,我们可以通过 Servlet API 中的 HttpServletResponse 类,设置文件下载时的 MIME 类型和文件名,然后将文件数据写入到 HTTP 响应的输出流中即可。

下面是一个简单的示例,展示如何实现文件下载:

public class ServletFileDownloadHandler extends HttpServlet {

  private static final long serialVersionUID = 1L;

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String filePath = request.getParameter("file");
    File downloadFile = new File(filePath);

    if (downloadFile.exists()) {
      //设置文件类型
      response.setContentType("application/octet-stream");
      //设置Content-Disposition头以弹出文件下载对话框
      response.setHeader("Content-Disposition", "attachment;filename=\"" + downloadFile.getName() + "\"");

      byte[] buf = new byte[4096];
      int len = -1;
      try (InputStream is = new FileInputStream(downloadFile)) {
          OutputStream os = response.getOutputStream();
          while ((len = is.read(buf)) != -1) {
              os.write(buf, 0, len);
          }
          os.flush();
      } catch (IOException e) {
          // 处理文件下载异常
      }
    } else {
      response.getWriter().write("The file does not exist!");
    }
  }
}

在上面的示例中,Servlet 接收请求参数 file,然后尝试读取该文件并将其写入 HTTP 响应的输出流中。需要注意的是,在实际应用中,我们应该对文件存在性进行校验,避免服务器内部错误和 XSS 等风险问题。

我们也可以使用第三方框架,如 Spring MVC 来实现复杂的文件下载,下面是一个示例:

@Controller
public class FileDownloadController {

  @RequestMapping(value = "/download/{fileName:.+}", method = RequestMethod.GET)
  public void downloadFile(@PathVariable("fileName") String fileName, HttpServletResponse response) throws IOException {
    File downloadFile = new File("/path/to/file/" + fileName);

    if (downloadFile.exists()) {
      response.setContentType("application/octet-stream");
      response.setContentLength((int) downloadFile.length());
      response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");

      try (InputStream is = new FileInputStream(downloadFile)) {
        IOUtils.copy(is, response.getOutputStream());
        response.flushBuffer();
      }
    } else {
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
    }
  }
}

上面的示例中使用了 Spring MVC 的 @Controller 注解,灵活的请求路径和参数映射方式,以及更加简便的 IO 流处理方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现文件上传和下载的方法详解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • SpringBoot基于AbstractRoutingDataSource实现多数据源动态切换

    下面就来详细讲解“SpringBoot基于AbstractRoutingDataSource实现多数据源动态切换”的完整攻略: 什么是AbstractRoutingDataSource Spring中提供了AbstractRoutingDataSource抽象类,该抽象类继承自AbstractDataSource类,用于实现多数据源的动态切换。继承该抽象类并…

    Java 2023年5月20日
    00
  • mybatis generator 配置 反向生成Entity简单增删改查(推荐)

    这里简单介绍一下使用MyBatis Generator配合MyBatis Plus快速生成增删改查的简单攻略,涉及到以下步骤: 添加相关依赖:在项目中添加MyBatis Generator依赖和MyBatis Plus依赖,例如在Maven项目中的pom.xml文件中添加如下依赖: <dependencies> <dependency&gt…

    Java 2023年5月20日
    00
  • Java MultipartFile实现上传文件/上传图片

    接下来我将为您详细讲解如何使用Java MultipartFile实现上传文件/上传图片的完整攻略。 什么是Java MultipartFile MultipartFile是Spring框架内置的一个接口,用于处理HTTP的多部分请求,用于上传文件/上传图片,它可以用于处理在表单中上传的文件,支持大文件上传和多文件上传。 实现上传文件/上传图片的完整攻略 下…

    Java 2023年5月20日
    00
  • JS笛卡尔积算法与多重数组笛卡尔积实现方法示例

    JS笛卡尔积算法用来计算多个数组的所有组合结果,它可以轻松地计算多个数组之间的笛卡尔积。下面是JS笛卡尔积算法的实现过程: 实现过程 首先我们需要创建一个空的结果数组,用于存储所有的组合结果。 然后我们需要用for循环嵌套来遍历所有的数组元素。 在遍历的过程中,我们需要用concat方法将数组元素进行组合,并将组合结果添加到结果数组中。 最后,我们返回结果数…

    Java 2023年5月19日
    00
  • struts2获取服务器临时目录的方法

    获取服务器临时目录是web开发中经常需要用到的功能,下面是详细讲解“struts2获取服务器临时目录的方法”的完整攻略: 1. 获取ServletContext对象 在struts2中获取服务器临时目录,需要先获取ServletContext对象。可以通过继承ActionContext类来获取: import com.opensymphony.xwork2.…

    Java 2023年5月20日
    00
  • Java解码H264格式视频流中的图片

    针对“Java解码H264格式视频流中的图片”的需求,我整理了以下完整攻略: 确定准备工作 了解H.264编解码标准及相关概念(可以参考视频编解码入门知识); 熟悉Java开发语言以及常用的流处理库,如Netty、I/O等; 确定H.264格式视频流的来源和传输方式。 解码H.264视频流 接收H.264视频流; 使用H.264解码器库,例如h264lib、…

    Java 2023年5月20日
    00
  • Springboot启动扩展点超详细教程小结

    Spring Boot启动扩展点是Spring Boot提供的一种机制,可以在Spring Boot启动过程中执行自定义的逻辑。以下是一个完整的Spring Boot启动扩展点攻略,包括如何创建和使用Spring Boot启动扩展点。 创建Spring Boot启动扩展点 我们可以通过实现org.springframework.boot.SpringAppl…

    Java 2023年5月14日
    00
  • Java13 明天发布(最新最全新特性解读)

    Java13 发布攻略 Java13 于 2019年9月17日发布,在这篇文档中,我们将介绍 Java13 的最新特性。 1. 新特性 以下是 Java13 中的一些新特性: 1.1 Switch 表达式 Java 13 可以使用新的关键字 yield 或 -> 来作为 switch 表达式的返回值。这使得代码更加简洁。 下面是一个例子: public…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部