spring-mvc之文件上传与下载

配置

spring-boot中,起步依赖自动添加了需要的库,并自动配置了 MultipartResolver 解析器,所以这步只针对直接使用spring的情况

spring-webmvc基于Apache提供的2个库实现文件的上传与下载

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.8.0</version>
</dependency>

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

配置MultipartResolver组件

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

文件上传

官方文档参考

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-multipart-forms

Spring中文件上传的核心是使用 MultipartFile 类型的参数接收文件数据。

MultipartFile提供了以下常用方法

  • boolean isEmpty() - 判断表单文件是否为空
  • String getOriginalFilename(); - 获取文件名
  • String getContentType() - 获取文件类型
  • long getSize() - 获取文件大小
  • byte[] getBytes() - 将文件转换为字节数组
  • InputStream getInputStream() - 将文件转换为输入流
  • void transferTo(File dest) - 文件保存的快捷方式
  • void transferTo(Path dest)

另外,spring-boot文件上传默认配置中,单文件限制大小为1MB,单次请求文件总大小限制为10MB,可以使用以下方式修改默认值

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 2MB # 单文件大小限制
      max-request-size: 10MB # 文件总大小限制

单文件上传示例

HTML表单

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

控制器代码

@PostMapping("/file/upload")
@ResponseBody
public String uploadFile(@RequestParam("file")MultipartFile file)
{
    if(!file.isEmpty())
    {
        String fileName=file.getOriginalFilename();
        String basePath="/home/lyp/Projects/spring-boot/web/src/main/resources/res";
        try
        {
            File f=new File(basePath,fileName);
            file.transferTo(f);
            return "上传成功";
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }
    return "上传失败";
}

多文件上传示例

HTML表单

<form action="/files/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="files" multiple>
    <button type="submit">上传</button>
</form>

控制器中只需要接收MultipartFile数组或List即可

@PostMapping("/files/upload")
@ResponseBody
public String uploadFiles(@RequestParam("files") List<MultipartFile> files)
{
    String basePath = "/home/lyp/Projects/spring-boot/web/src/main/resources/res";
    try
    {
        for(MultipartFile file: files)
        {
            if(!file.isEmpty())
            {
                String fileName = file.getOriginalFilename();
                File f = new File(basePath,fileName);
                file.transferTo(f);
            }
        }
        return "上传成功";
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }

    return "上传失败";
}

文件下载

使用Servlet相关的API即可,唯一需要注意的是设置响应头信息

这里测试图片在res目录下,客户端之所以直接从根路径访问而不用加res前缀,是因为额外将res目录配置到spring-boot的静态资源查找路径中了。
配置方法就是使用 static-locations 选项。

HTML代码

<img src="/test.png" alt="">
<a href="/file/download?filename=test.png">下载</a>

控制器代码

@GetMapping("/file/download")
@ResponseBody
public String download(@RequestParam("filename") String filename,
                        HttpServletResponse resp)
{
    if(filename!=null && !filename.isBlank())
    {
        String basePath = "/home/lyp/Projects/spring-boot/web/src/main/resources/res";
        File file=new File(basePath,filename);
        if(file.exists())
        {
            resp.setContentType("application/forc-download");
            resp.setHeader("Content-Disposition","attachment;filename="+filename);
            try(ServletOutputStream out=resp.getOutputStream();)
            {
                Path path=Path.of(file.toURI());
                byte[] bytes = Files.readAllBytes(path);
                out.write(bytes);
                out.flush();
                return "下载成功";
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    return "下载失败";
}
posted @ 2021-07-05 16:11  lypzzzz  阅读(151)  评论(0)    收藏  举报