当前位置 : 主页 > 编程语言 > java >

SpringMVC文件上传与下载

来源:互联网 收集:自由互联 发布时间:2023-10-10
一、文件上传 首先,http上传时候的content-type为 multipart/form-data ,默认情况下SpringMVC对该种类型报文的解析器为 org.springframework.web.multipart.MultipartResolver 类型的对象。MultipartResolver本身是个


一、文件上传

首先,http上传时候的content-type为multipart/form-data,默认情况下SpringMVC对该种类型报文的解析器为 org.springframework.web.multipart.MultipartResolver 类型的对象。MultipartResolver本身是个接口,其实现类为 org.springframework.web.multipart.support.StandardServletMultipartResolver

需要说明的是,CommonsMultipartResolver从 Spring Framework 6.0 及其新的 Servlet 5.0+ 基线开始,基于 Apache Commons FileUpload 的过时版本不再可用

SpringMvc在初始化时会从IOC中获取名为”multipartResolver“类型为MultipartResolver类型的Bean作为multipartResolver。 

在Springboot的org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中对要使用的multipartResolver进行了配置,具备配置在org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration中,其配置如下

@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
@ConditionalOnMissingBean(MultipartResolver.class)
public StandardServletMultipartResolver multipartResolver() {
		StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
		multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
		return multipartResolver;
}

可见其默认使用的就是StandardServletMultipartResolver。

我们可以通过配置来对文件大小,存储路径等进行设置,如下:

spring.servlet.multipart.enabled=true
#	servlet 接受到文件的时候,会先将其保存在一个临时目录
# 这个参数就可以指定这个目录的位置
spring.servlet.multipart.location=
#允许上传的文件最大值,默认为-1,表示没有限制
spring.servlet.multipart.maxFileSize=-1
#针对 multipart/form-data 请求的最大数量,默认为-1,表示没有限制
spring.servlet.multipart.maxRequestSize=-1
#文件大小超过这个值的会被写入磁盘,默认值为 0,都会写入磁盘,
#小于这个值的会被写在内存中。单位:byte
spring.servlet.multipart.fileSizeThreshold=0

StandardServletMultipartResolver作用就是从HttpServletRequest中获取Part,然后对其进行封装成MultipartFile对象

方式1:原生方式上传

@MultipartConfig(
	location="",
    maxFileSize=-1,
    maxRequestSize=-1,
    fileSizeThreshold=50*1024*1024
)
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    public void upload(HttpServletRequest request){
        //方式1:读取指定参数的单个文件
        Part part = request.getPart("file1");

        //方式2:获取请求中所有参数的文件集合
        Collection parts = req.getParts();

        //获取文件名
        String fileName = part.getSubmittedFileName();

        //读取文件内容并写入文件
        part.write(realPath + "/" + fileName);
        //删除临时文件
        part.delete();
    }
}


方式2:SpringMvc中上传

@RestController
@RequestMapping("/upload")
public class UploadController {
 
    /**
    * 说明:这里用了注解@RequestPart,除此以外@RequestParam也是可用的。
    * @RequestPart注解解析的是multipart/form-data表单中的数据,
    *    可以支持文件参数 如MultipartFile
    * @RequestParam 能解析请求格式为‘application/json’的数据 ,
    *    同样也支持‘multipart/form-data’
    *
    * 1、当请求的contentType为“multipart/form-data”的时候@RequestParam
         只能解析出String类型的 key-value的这种数据而@RquestPart可以接收
         复杂的请求域如:json,xml,字节
    * 2、@RequstParam依赖 Converter or PropertyEditor对数据进行解析,
         @RequestPart参考‘contentType’依赖HttpMessageConverts对数据
         进行解析
    */
  	@PostMapping("/file1")
    public void upload1(@RequestPart MultipartFile file){
        //destFile为目标文件,即将上传的文件写到destFile中
 		file.transferTo(destFile);
    }
    
    @PostMapping("/file2")
    public void upload2(@RequestPart("param1") MultipartFile file){
    }
    
    @PostMapping("/file3")
    public void upload3(@RequestPart("param1") MultipartFile file1,
                       @RequestPart("param2") MultipartFile file2){
    }
    
    @PostMapping("/file4")
    public void upload4(MultipartFile[] fils) {}
    
    @PostMapping("/file5")
    public void upload5(MultipartHttpServletRequest request) {
        //1.获取表单中非文件数据
        Map parameterMap = request.getParameterMap();
    	//2、获取表单中文件数据
    	MultiValueMap multiFileMap = request.getMultiFileMap();
    }
}


二、文件下载

方法1:使用HttpServletResponse

@RestController
@RequestMapping("/download")
@Tag(name = "文件下载示例")
public class DownloadController {

	@Operation(summary = "访问我下载文件了")
    @GetMapping("/v1")
    public void download1 (HttpServletResponse response) {
        //1. 接受文件名,读取磁盘对应的文件,创建输入流对象
		FileInputStream inputStream = new FileInputStream("C:/"+fileName);
		//2.获取响应对象的输出流
		ServletOutputStream outputStream = response.getOutputStream();
		//3.文件下载文件名的编码使用ISO-08859-1编码
		//我们需要将我们UTF-8的 filename转换ISO-8859-1编码
		//3.1先将字符串以UTF-8转换成字节数组
		byte[] bytes = fileName.getBytes("UTF-8");
		//3.2再将字节数组以 ISO-8859-1转换字符串
		fileName = new String(bytes, "ISO-8859-1");
		//4.响应的内容应该是以附件的形式响应给浏览器(设置响应头)
		response.setHeader("Content-Disposition", "attachment;filename="+fileName);
		//5.响应文件给浏览器
		IOUtils.copy(inputStream, outputStream);
        //6.关闭流
        inputStream.close();
        outputStream.close();
    }
}


方法2:使用ResponseEntity

@RestController
@RequestMapping("/download")
@Tag(name = "文件下载示例")
public class DownloadController {

    @Operation(summary = "访问我下载文件了")
    @GetMapping("/v1")
    public ResponseEntity<Resource> download1 () {
        //要下载的文件路径
        Path path = Paths.get(".......") ;
        Resource resource = new InputStreamResource(Files.newInputStream(path));
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="
                + URLEncoder.encode(fileInfo.getOriginalName(), "UTF-8"));
        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(Files.size(path))
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource) ;
    }
    
    @Operation(summary = "访问我下导出excel文件了")
    @GetMapping("/v2")
    public ResponseEntity<Resource> download2 () {
        //查询数据库得到的数据 TODO 
        List<DataEntity> dataList = null ;
        if(dataList == null){
            dataList = new ArrayList<>() ;
        }
        //输出excel格式数据(这里使用了EasyExcel组件)
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream() ;
        EasyExcel.write(outputStream, DataEntity.class)
                .sheet("数据")
                .doWrite(dataList);
        
        /*
        多个sheet输出:
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream() ;
        ExcelWriter excelWriter = EasyExcel.write(outputStream).build() ;
        try{
            // 写出sheet数据
            doWriteSheet(excelWriter,"我是sheet1",XXXDto.class,xxxDtoList);
            doWriteSheet(excelWriter,"我是sheet2",YYYDto.class,yyyDtoList);
        }finally {
            // 关流
            excelWriter.finish();
        }
        */
        
        String fileName = "下载文件.xlsx" ;
        //字节数
        long contentLength = outputStream.size() ;
        //进行数据的写出
        Resource resource =  new ByteArrayResource(outputStream.toByteArray()) ;
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="
                    + URLEncoder.encode(fileName, "UTF-8"));
        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(contentLength)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource) ;
    }
    
    private void doWriteSheet(ExcelWriter excelWriter,String sheetName,Class<?> clazz,List data){
        // 构建sheet对象
        WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).head(clazz).build();
        // 写出sheet数据
        excelWriter.write(data, writeSheet);
    }
}


上一篇:springboot启动前执行方法代码的几种方式
下一篇:没有了
网友评论