最终效果图(简单案例,模拟的是上传到本地,本应该是上传到服务器的)

页面批量下载java java实现批量下载_spring boot


1、依赖及yml配置

<!--文件上传下载-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

在yml文件中配置存储的路径

url:
  F://train/ # 本地存储文件的路径

2、数据库,只需要id,文件名,还有文件url就可以,我这里因为是模拟上传到本地,所以url都是本地盘符下的

页面批量下载java java实现批量下载_java_02


建表sql语句

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for my_file
-- ----------------------------
DROP TABLE IF EXISTS `my_file`;
CREATE TABLE `my_file`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `file_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `file_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

3、创建文件的实体类与数据库表中字段对应

import lombok.Data;

@Data
public class MyFile {
    private int id;
    private String fileName;
    private String fileUrl;
}

4、Mapper层使用MybatisPlus继承了BaseMapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.limou.pojo.MyFile;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MyFileMapper extends BaseMapper<MyFile> {
}

5、Service层接口提供了三个方法,上传下载以及展示所有

import com.limou.pojo.MyFile;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;

public interface MyFileService {

    // 上传
    Map<String, Object> uploadFile(MultipartFile file);

    // 下载
    ResponseEntity<byte[]> downloadFile(String fileUrl, String fileName);

    // 查询所有
    List<MyFile> list();
}

其中Service实现类是实现上传下载的核心,业务处理我们一般都写在service层

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.limou.mapper.MyFileMapper;
import com.limou.pojo.MyFile;
import com.limou.service.MyFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class MyFileServiceImpl implements MyFileService {

    @Value("${url}")
    private String address;

    @Autowired
    private MyFileMapper mapper;

    /**
     * 上传文件
     * @param file 文件对象
     * @return
     */
    @Override
    public Map<String, Object> uploadFile(MultipartFile file) {

        Map<String, Object> map = new HashMap<>();

        String lastName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        // 获取当前系统日期
        String dateTime = simpleDateFormat.format(new Date());

        // 随机数
        String uuid = UUID.randomUUID() + "";

        // 最后要文件上传的路径
        String fileAddress = address + dateTime + "/" + uuid + "." + lastName;

        // 创建文件对象
        File uploadFile = new File(fileAddress);
        if (!uploadFile.isDirectory()) {
            // 创建文件
            uploadFile.mkdirs();
        }

        try {
            file.transferTo(uploadFile);
        } catch (IOException exception) {
            log.error(exception.getMessage());
            map.put("msg", "上传失败");
            return map;
        }

        MyFile myFile = new MyFile();
        myFile.setFileName(file.getOriginalFilename());
        myFile.setFileUrl(fileAddress);

        mapper.insert(myFile);

        map.put("myFile", myFile);
        map.put("msg", "上传成功");
        return map;
    }


    /**
     * 下载文件
     * @param fileUrl 文件路径
     * @param fileName 文件名
     * @return
     */
    @Override
    public ResponseEntity<byte[]> downloadFile(String fileUrl, String fileName) {

        QueryWrapper<MyFile> wrapper = new QueryWrapper<>();
        wrapper.eq("file_url", fileUrl);
        List<MyFile> myFiles = mapper.selectList(wrapper);

        if (myFiles != null && myFiles.size() == 1) {

            // 创建文件夹对象
            File file = new File(fileUrl);
            // 通过浏览器响应下载文件
            HttpHeaders httpHeaders = new HttpHeaders();
            // 二进制方式输出
            httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            try {
                String fileName2 = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                httpHeaders.set("Content-Disposition", "attachment;filename=" + fileName2);
                // 转换成字节码
                byte[] bytes = FileUtils.readFileToByteArray(file);
                return new ResponseEntity<byte[]>(bytes, httpHeaders, HttpStatus.OK);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return null;

    }

    @Override
    public List<MyFile> list() {
        return mapper.selectList(null);
    }
}

6、controller层只需要调用service层接口,对外提供访问的url就可以

import com.limou.pojo.MyFile;
import com.limou.service.MyFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;

@RequestMapping("/file")
@Controller
public class MyFileController {

    @Autowired
    private MyFileService myFileService;

    // 上传
    @RequestMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile multipartFile){
        myFileService.uploadFile(multipartFile);
        return "redirect:list";
    }

    // 下载
    @RequestMapping("/download")
    public ResponseEntity<byte[]> downloadFile(String fileUrl, String fileName){
        System.out.println("fileUrl:------" + fileUrl);
        System.out.println("fileName:-----" + fileName);
        return myFileService.downloadFile(fileUrl, fileName);
    }

    // 展示列表
    @RequestMapping("/list")
    public String list(Model model){
        List<MyFile> list = myFileService.list();
        System.out.println(list);
        model.addAttribute("list", list);
        return "fileList";
    }
}

7、html代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>

<h1>文件上传</h1>
<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="上传">
</form>

<hr>

<h1>文件下载</h1>

<table class="table table-hover text-center">
    <tr>
        <th style="text-align:left; padding-left:20px;" width="100">ID</th>
        <th>文件名</th>
        <th>文件路径</th>
        <th width="310">操作</th>
    </tr>

  <tr th:each="file : ${list}">
        <td th:text="${file.id}"></td>
        <td th:text="${file.fileName}"></td>
        <td th:text="${file.fileUrl}"></td>
        <td>
            <a th:href="@{download(fileName=${file.fileName},fileUrl=${file.fileUrl})}">下载</a>
        </td>
    </tr>
</table>

</body>
</html>
  • 下边这里是实现勾选批量下载为zip的方法
    效果展示如下

    前端html代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
    <meta content="IE=edge" http-equiv="X-UA-Compatible">
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
    <meta content="webkit" name="renderer">
    <title></title>
    <link href="../css/pintuer.css" rel="stylesheet">
    <link href="../css/admin.css" rel="stylesheet">
    <script src="../js/jquery.js"></script>
    <script src="../js/pintuer.js"></script>
</head>
<body>
<h1>文件上传</h1>
<form action="upload" enctype="multipart/form-data" method="post">
    <input name="file" type="file">
    <input type="submit" value="上传">
</form>

<hr>
<h1>文件下载</h1>

<form action="downloads">
    <table class="table table-hover text-center">
        <tr>
            <th style="text-align:left; padding-left:20px;" width="100">ID</th>
            <th>文件名</th>
            <th>文件路径</th>
            <th width="310">操作</th>
        </tr>

        <tr th:each="file : ${list}">
            <td>
                <input name="ids" th:value="${file.id}" type="checkbox">
                <span th:text="${file.id}"></span>
            </td>
            <td th:text="${file.fileName}"></td>
            <td th:text="${file.fileUrl}"></td>
            <td>
                <a th:href="@{download(fileName=${file.fileName},fileUrl=${file.fileUrl})}">下载</a>
            </td>
        </tr>
    </table>

    <input type="submit" value="批量下载">
</form>


</body>
</html>

contoller层代码(仍然是去直接调用service层代码,但需要前端传递多个id的信息,以及httpServletResponse对象,获取输出流)

// 批量下载
    @RequestMapping("/downloads")
    public void downloadFiles(String ids, HttpServletResponse httpServletResponse){
        // System.out.println(ids);
        myFileService.downloadFiles(ids, httpServletResponse);
    }

service层代码

接口

// 批量下载
    void downloadFiles(String ids,  HttpServletResponse response);

实现类(核心)

// 批量下载
    @Override
    public void downloadFiles(String ids, HttpServletResponse response) {

        List<Map> fileList = new ArrayList<>();

        // 拿到id的集合
        List<String> idList = Arrays.asList(ids.split(","));
        // url集合
        List<String> urlList = new ArrayList<>();
        for (String id : idList) {
            // 添加到url集合
            urlList.add(mapper.selectById(id).getFileUrl());
        }
        
        try {
            for (int i = 0; i < urlList.size(); i++) {
                // 创建文件对象
                File file = new File(urlList.get(i));

                // 转换成字节
                byte[] bytes = FileUtils.readFileToByteArray(file);
                // 存入Map
                Map map = new HashMap();
                String fileName = UUID.randomUUID() + "." + urlList.get(i).substring(urlList.get(i).lastIndexOf(".") + 1);
                map.put("fileName", fileName);
                map.put("outByte", bytes);

                fileList.add(map);
            }
        } catch (IOException exception) {
            exception.printStackTrace();
        }

        try (ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) {
            // 创建 ZipEntry 对象
            for (Map mapNow : fileList) {
                ZipEntry zipEntry = new ZipEntry((String) mapNow.get("fileName"));
                zipOutputStream.putNextEntry(zipEntry);
                zipOutputStream.write((byte[]) mapNow.get("outByte"));
            }
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }

其余部分同上

综合我的上一篇博客关于Excel的导入与导出,大致可以做到如下效果

页面批量下载java java实现批量下载_spring_03