JAVA实现带表单参数的文件上传、下载和文件打包下载

准备工作

  1. springboot框架
  2. maven
  3. Spring Data JPA

1、文件上传

我是上传封装起来的,方便调用,直接上代码

public static void uploadFile(String filePath, String fileName, MultipartFile multipartFile) throws Exception {

        File file = new File(filePath + fileName);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        multipartFile.transferTo(file);
    }

第一个参数是要上传的位置,如果是本地可以是某一个盘下的文件夹路径,第二个参数是获取到的文件名字,第三个参数是我们使用Multipart来实现文件上传,下面会有演示
上传方法调用

    @Autowired
    FileRepository fileRepository;

    @PostMapping(value = "/submit")
    @ResponseBody
    public ModelAndView uploadFile(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "file") MultipartFile multipartFile) throws UnsupportedEncodingException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        Long length = multipartFile.getSize(); // 返回的是字节,1M=1024KB=1048576字节 1KB=1024Byte
        String fileName = multipartFile.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".")).toLowerCase().trim(); // 文件后缀名
        //String prefix = fileName.substring(0,fileName.lastIndexOf(".")); // 文件后缀名

        String fileType = ".txt,.docx,.doc";
        //String[] typeArray = fileType.split(",");

        String error[] = {"文件内容为空 !","文件大小限制1M !","文件后缀名有误 !","提交成功!","提交失败,请与工作人员联系"};

        ModelAndView mav = new ModelAndView();

        if (multipartFile.isEmpty()) {
            mav.setViewName("message");
            mav.addObject("error",error[0]);
            return mav;
        } else if (length > 1048576) {
            mav.setViewName("message");
            mav.addObject("error",error[1]);
            return mav;
        } else if (!Arrays.asList(fileType.split(",")).contains(suffix)) {
            mav.setViewName("message");
            mav.addObject("error",error[2]);
            return mav;
        }

        Files files = new Files();
        String filePath = "/file/UploadFiles" + "/" + UUID.randomUUID() + "/";
        //String filePath = request.getSession().getServletContext().getRealPath("/") + "upload/";
        String fileUrl = filePath + fileName;
        files.setName(fileName);
        files.setUrl(fileUrl);
        files.setDate(new Timestamp(System.currentTimeMillis()));

        try {
            FileUtil.uploadFile(filePath, fileName, multipartFile);
            fileRepository.save(files);

            mav.setViewName("message");
            mav.addObject("error",error[3]);
            return mav;
        } catch (Exception e) {
            e.printStackTrace();

            mav.setViewName("message");
            mav.addObject("error",error[4]);
            return mav;
        }
    }

在这里我进行了文件后缀名和大小等一系列的判断,并将文件的存储路径存到了数据库,这个在后面压缩文件会用到
这里的@RequestParam(value = “file”) MultipartFile multipartFile中的 multipartFile就是前面说的要给上传方法传的第三个参数,当然我这里使用的是自动注入,value = “file”就是表单中file输入框name属性的名字,如下:

<form action="/submit" method="post" enctype="multipart/form-data">
                <div class="row">
                    <div class="col-md-12">
                        <div class="add-box">
                            <input type="file" name="file id="file"/>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="submit-box">
                        <input type="submit" name="submit" value="提交" id="submit" class="btn-submit"/>
                    </div>
                </div>
            </form>

特别注意,表单要加属性 enctype=”multipart/form-data”
这里我自定义的文件类也是File,注意与IO的File类的区别

File类

@Entity
@Table(name = "files")
@Getter
@Setter
@ToString
public class Files implements Serializable {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;
    private String url;
    private Timestamp date;
}

用的Lombok,减少了get和set方法的书写,不知道的可以直接写get、set方法

2、文件打包下载

文件压缩方法方法封装:

public static void zipFile(File zipPath, List<Files> filesList) {

        FileOutputStream fileOutput;
        ZipOutputStream zipOutput;
        BufferedOutputStream bufferedOutput;
        FileInputStream fileInput = null;
        BufferedInputStream bufferedInput = null;
        try {
            fileOutput = new FileOutputStream(zipPath); // 输出流,压缩包所在路径
            bufferedOutput = new BufferedOutputStream(fileOutput);
            zipOutput = new ZipOutputStream(bufferedOutput);

            for (int i = 0;i<filesList.size();i++) {
                Files files = filesList.get(i);
                File filePath = new File(files.getUrl()); // 待压缩文件路径
                // 压缩条目
                ZipEntry entry = new ZipEntry(i+"."+filePath.getName());
                // 读取待压缩的文件并写进压缩包里
                fileInput = new FileInputStream(filePath);
                bufferedInput = new BufferedInputStream(fileInput);
                zipOutput.putNextEntry(entry);
                byte[] buffer = new byte[8192];//官方API文档推荐大小8192
                int num;
                while ((num = bufferedInput.read(buffer)) != -1) {
                    zipOutput.write(buffer,0,num);
                }
                // 不能写成  int i = bufferedInput.read(buffer);while(i != -1);否则形成死循环,一直写入
            }

            zipOutput.closeEntry();
            fileInput.close();
            bufferedInput.close();
            zipOutput.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

方法调用:

    @RequestMapping(value = "/zipDownload")
    @ResponseBody
    public void downloadZip(HttpServletResponse response) {

        List<Files> filesList = fileRepository.findAll();

        String zipName = "file.zip";
        String outPath = "/file/";
        File zipPath = new File(outPath, zipName); // 使用IO的File根据路径获取文件

        try {
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setHeader("content-type", "application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipName, "UTF-8")); // 解决中文名乱码
            OutputStream output = response.getOutputStream(); // 得到服务器的输入流

            FileUtil.zipFile(zipPath, filesList);
            FileUtil.downloadFile(zipPath, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

这里的fileList就是要压缩文件的路径,因为多个文件,所以是集合,这个路径集合是从数据库中查询出来的,上面有提到
outPath是压缩生成的文件所在位置,zipName是生成压缩文件的名字

3、文件下载

下载封装方法

public static void downloadFile(File file, OutputStream output) {

        FileInputStream fileInput = null;
        BufferedInputStream inputStream = null;
        try {
            fileInput = new FileInputStream(file);
            inputStream = new BufferedInputStream(fileInput);
            byte[] buffer = new byte[8192];//1024*8
            int i;
            while ((i = inputStream.read(buffer)) != -1) {
                output.write(buffer,0,i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null)
                    inputStream.close();
                if (fileInput != null)
                    fileInput.close();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

方法调用

    @RequestMapping(value = "/fileDownload")
    @ResponseBody
    public void downloadFile(HttpServletResponse response) {

        String fileName = "下学期公式表.doc";
        String filePath = "/file/";
        File file = new File(filePath, fileName);

        try {
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setHeader("content-type", "application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            OutputStream output = response.getOutputStream();

            FileUtil.downloadFile(file, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

fileName是要下载文件的名字,filePath是文件的位置,使用IO的File类将二者拼装在一起,这里我用的是Linux服务器的路径,windows可以自行更改

4、带表单参数的文件上传

文件上传方法同上
表单如下:

<form action="/formfile" method="post" enctype="multipart/form-data" onsubmit="return validate()">
                <div class="row">
                    <div class="col-md-12">
                        <div class="add-box">
                            <input type="file" name="file" id="file"/>
                        </div>
                    </div>
                </div>
                名字:<input type="text" name="username" />
                密码:<input type="password" name="password" />
                <div class="row">
                    <div class="submit-box">
                        <input type="submit" name="submit" value="提交" id="submit" class="btn-submit"/>
                    </div>
                </div>
            </form>

控制类:

    @PostMapping(value = "/formfile")
    @ResponseBody
    public ModelAndView formUploadFile(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        /*
        或者
        单文件
        public ModelAndView formUploadFile(@RequestParam(value = "file") MultipartFile multipartFile) {}
        多文件
        public ModelAndView formUploadFile(@RequestParam(value = "file") MultipartFile[] multipartFile) {}
        */

        //List<MultipartFile> files = ((MultipartHttpServletRequest)request).getFiles("files");
        //for (int i = 0;i<files.size();i++) {
        //    MultipartFile multipartFile = files.get(i);
        //    String file = multipartFile.getName();
        //}
        // 多文件带参数上传

        MultipartFile multipartFile = ((MultipartHttpServletRequest) request).getFile("file"); // 单文件上传
        //MultipartFile multipartFile = multipartRequestgetFiles("file").get(0); // 多文件上传

        String username = request.getParameter("username"); // 获取表单参数
        String password = request.getParameter("password");

        Member member = new Member(username, password); // 生成对象,存入数据库

        Long length = multipartFile.getSize(); // 返回的是字节,1M=1024KB=1048576字节 1KB=1024Byte
        String fileName = multipartFile.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".")).toLowerCase().trim(); // 文件后缀名
        //String prefix = fileName.substring(0,fileName.lastIndexOf(".")); // 文件后缀名

        String fileType = ".txt,.docx,.doc";
        //String[] typeArray = fileType.split(",");

        String error[] = {"文件内容为空 !", "文件大小限制1M !", "文件后缀名有误 !", "提交成功!", "提交失败,请与工作人员联系"};

        ModelAndView mav = new ModelAndView();

        if (multipartFile.isEmpty()) {
            mav.setViewName("message");
            mav.addObject("error", error[0]);
            return mav;
        } else if (length > 1048576) {
            mav.setViewName("message");
            mav.addObject("error", error[1]);
            return mav;
        } else if (!Arrays.asList(fileType.split(",")).contains(suffix)) {
            mav.setViewName("message");
            mav.addObject("error", error[2]);
            return mav;
        }

        Files files = new Files();
        //String filePath = "/file/UploadFiles" + "/" + UUID.randomUUID() + "/";
        //String filePath = request.getSession().getServletContext().getRealPath("/") + "upload/";
        String filePath = "F:\\文件";
        String fileUrl = filePath + fileName;
        files.setName(fileName);
        files.setUrl(fileUrl);
        files.setDate(new Timestamp(System.currentTimeMillis()));

        try {
            FileUtil.uploadFile(filePath, fileName, multipartFile);
            fileRepository.save(files);
            memberRepository.save(member);

            mav.setViewName("message");
            mav.addObject("error", error[3]);
            return mav;
        } catch (Exception e) {
            e.printStackTrace();

            mav.setViewName("message");
            mav.addObject("error", error[4]);
            return mav;
        }
    }

Member实体类

@Entity
@Table(name = "member")
@Setter
@Getter
public class Member {

    @Id
    @GeneratedValue
    private Integer id;

    String username;
    String password;

    public Member() {}

    public Member(String username,String password) {
        this.username = username;
        this.password = password;
    }
}

其他

message.html信息提示页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>信息提示</title>
</head>
<body>
<br/><br/><br/>
<center>
    <h1><p th:text="${error}"></p></h1>
</center>
</body>
</html>

配置文件:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/fantasticpan?useUnicode=true&amp;characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root

spring.thymeleaf.cache=false
spring.jpa.hibernate.ddl-auto=update
spring.jackson.serialization.indent-output=true

spring.http.multipart.max-file-size=1MB
spring.http.multipart.max-request-size=1MB

server.port=9999

这里设置了文件上传大小的限制

猜你喜欢

转载自blog.csdn.net/swpu_lipan/article/details/79157080