• 0062 Spring MVC的文件上传与下载--MultipartFile--ResponseEntity


    文件上传功能在网页中见的太多了,比如上传照片作为头像、上传Excel文档导入数据等

    先写个上传文件的html

    <!DOCTYPE html>
    <html>
    <head>
        <title>Spring MVC文件上传与下载</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   
    </head>
        <body>
            <form action="upload" method="POST" enctype="multipart/form-data">   <!-- 上传文件注意enctype -->
                文件描述:<input type="text" name="desc" /> <br><br>
                选择文件:<input type="file" name="file" /> <br><br>
                <input type="submit" value="上传" /> 
            </form>
        </body>
    </html>
    

    写个controller接收上传的文件

    package net.sonng.mvcdemo.controller;
    
    import java.io.File;
    
    import javax.servlet.http.HttpServletRequest;
    
    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;
    
    @Controller
    public class UploadController {
        @RequestMapping("/upload")
        public String upload(HttpServletRequest request,@RequestParam("desc") String desc,@RequestParam("file") MultipartFile file) throws Exception{
            //接收到的文件绑定到MultipartFile对象中
            System.out.println(desc);
            if (!file.isEmpty()){  //如果文件不为空,那么将它存起来
                String path=request.getServletContext().getRealPath("/images");  //接收的文件放在/images目录下,并获得文件系统目录
                String filename=file.getOriginalFilename();//获取文件名
                File filepath=new File(path,filename);     //根据文件所在目录和文件名创建File对象
                if(!filepath.getParentFile().exists()){    //如果所在目录不存在,那么创建
                    filepath.getParentFile().mkdirs();
                }
                file.transferTo(new File(path+File.separator+filename)); //调用transferTo()方法将文件存储到目标位置
                //file.transferTo(filepath)                              //也可以用这条语句
                return "result";
            }else{
                return "error";
            }
        }
    }
    

    关于multipartFile

    常用方法有:

    • String getContentType(): 获取文件的MIME类型
    • String getOriginalFilename(): 获取文件名
    • long getSize(): 获取文件大小,单位KB
    • boolean isEmpty(): 文件是否为空
    • void transferTo(File dest): 将文件存储到dest
    • String getName(): 获取表单的参数名
    • byte[] getBytes(): 获取文件数据
    • InputStream getInputStream(): 获取文件流

    Spring MVC的文件上传组件需要MultipartResolver接口,依赖于Apache Commons FileUpload技术实现了一个实现类CommonsMultipartResolver,因此还需要两方面的工作:1. 引入Apache Commons FileUpload包;2. 配置xml

    引入Apache Commons FileUpload及其依赖的Commons IO

    配置xml

     <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="maxUploadSize">    <!-- 还可以限制上传文件的大小 -->
                <value>10485760</value>
            </property>
            <property name="defaultEncoding" >  <!-- 注意这个编码格式,要跟上传的页面的编码一致 -->
                <value>UTF-8</value>
            </property>
        </bean>
    

    部署访问,检查Tomcat的该app目录下的/images目录下是否有上传的文件。

    将上传的文件以对象属性的形式保存

    比如头像,总是属于某个用户,因此在用户类中可以定义一个MultipartFile属性存储用户头像
    上传用户头像的html

    <!DOCTYPE html>
    <html>
    <head>
        <title>Spring MVC文件上传与下载</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
        <body>
            <form action="upload" method="POST" enctype="multipart/form-data">
                用户名:<input type="text" name="username" /> <br><br>
                选择图片:<input type="file" name="avatar" /> <br><br>
                <input type="submit" value="上传" /> 
            </form>
        </body>
    </html>
    

    实体类user:

    package net.sonng.mvcdemo.entity;
    
    import org.springframework.web.multipart.MultipartFile;
    
    public class User {
        private String username;
        private MultipartFile avatar;   //上传的头像作为User的一个属性
        //。。。。。  
    }
    

    写controller:

    package net.sonng.mvcdemo.controller;
    
    import java.io.File;
    
    import javax.servlet.http.HttpServletRequest;
    
    import net.sonng.mvcdemo.entity.User;
    
    import org.apache.commons.io.FileUtils;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @Controller
    public class UploadController {
        @RequestMapping("/upload")
        public String upload(HttpServletRequest request,@ModelAttribute User user,Model model) throws Exception{
            if (!user.getAvatar().isEmpty()){
                String path=request.getServletContext().getRealPath("/avatars/");
                String filename=user.getAvatar().getOriginalFilename();
                File filepath=new File(path,filename);
                if(!filepath.getParentFile().exists()){
                    filepath.getParentFile().mkdirs();
                }
                user.getAvatar().transferTo(new File(path+File.separator+filename));
                model.addAttribute("user", user);
                return "result";
            }else{
                return "error";
            }
        }
        @RequestMapping("/download")  //上传了之后再下载
        public ResponseEntity<byte[]> download(HttpServletRequest request,@RequestParam("filename") String filename,Model model)throws Exception{
            String path=request.getServletContext().getRealPath("/avatars/");  //获取文件所在路径
            filename=new String(filename.getBytes("ISO-8859-1"),"UTF-8");     //不知何故,result.jsp的请求参数是ISO-8859-1编码的,但明明设置了charset=utf-8
            File file=new File(path+File.separator+filename);
            HttpHeaders headers=new HttpHeaders();
            String downloadFileName=new String(filename.getBytes("UTF-8"),"ISO-8859-1");  //少了这句,可能导致下载中文文件名的文档,只有后缀名的情况
            headers.setContentDispositionFormData("attachment", downloadFileName);//告知浏览器以下载方式打开
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//设置MIME类型
            return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);//
            //用FileUpload组件的FileUtils读取文件,并构建成ResponseEntity<byte[]>返回给浏览器
            //HttpStatus.CREATED是HTTP的状态码201
        }
    }
    

    上传成功后,返回页面result.jsp,

    <%@page pageEncoding="utf-8" 
            contentType="text/html;charset=utf-8" %>
    <html>
        <head>
            <title>文件的上传与下载</title>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        </head>
        <body>
            <p>下载刚才上传的文件</p>
            <a href="download?filename=${user.avatar.originalFilename }">下载文件</a>
        </body>
    </html>
    

    部署测试,分别测试中文/英文文件名

    总结

    上传文件:上传的文件绑定到MultipartFile中;获取文件名;要存储的文件系统路径;创建目录;用MultipartFile的transferTo()存储
    下载文件:获取要下载的文件名,注意编码;在HttpHeaders中设置以下载方式打开,设置MIME类型;用FileUtils.readFileToByteArray()读取文件数据;用ResponseEntity<byte[]>构建返回对象

  • 相关阅读:
    PHP 魔术常量
    PHP 魔术方法
    php函数serialize()与unserialize()
    10 件有关 JavaScript 让人费解的事情
    windows下安装Python2和Python3共存
    SQL 行转列===列转行
    Redis 分布式锁
    RabbitMQ
    @Autowired
    AOP 日志切面
  • 原文地址:https://www.cnblogs.com/sonng/p/6664964.html
Copyright © 2020-2023  润新知