SpringMVC(六)——文件上传和下载

文件上传

1.需要导包

commons-fileupload

commons-io

2.请求方法的参数

MultipartFile类,全称org.springframework.web.multipart.MultipartFile。主要方法有

SpringMVC(六)——文件上传和下载

3.在springmvc-config.xml配置文件上传解析器

<!-- 文件上传解析器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>

还有其他属性可以设置,例如maxUploadSize表示上传文件的最大值等。

4.通过jsp的表单提交请求

(1)method设置为post

(2)enctype设置为multipart/form-data,浏览器会采用二进制流的方式处理表单数据,服务器端会对文件上传的请求进行解析处理。

(3)<input type="file" name="filename" />

测试用的jsp例子

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传</title>
<script>
// 判断是否填写上传人并已选择上传文件
function check(){
    var name = document.getElementById("name").value;
    var file = document.getElementById("file").value;
    if(name==""){
        alert("填写上传人");
        return false;
    }
    if(file.length==0||file==""){
        alert("请选择上传文件");
        return false;
    }
    return true;
}
</script>
</head>
<body>

    <form action="${pageContext.request.contextPath }/testup"
    method="post" enctype="multipart/form-data" onsubmit="return check()">
    上传人:<input id="name" type="text" name="name" /><br />
    请选择文件:<input id="file" type="file" name="uploadfile" multiple="multiple" /><br />
               <input type="submit" value="上传" />
    </form>
</body>
</html>

5.控制器类

@Controller
public class FileController {

    @RequestMapping("/testup")
    public String testUp(@RequestParam("name")String name,@RequestParam("uploadfile") List<MultipartFile> uploadfile,HttpServletRequest request ) {
        
        if(!uploadfile.isEmpty() && uploadfile.size()>0) {
            for(MultipartFile file:uploadfile) {
                String originalFilename=file.getOriginalFilename();//获取上传文件的原始名字
                String dirPath=request.getServletContext().getRealPath("/upload/");//设置上传文件的保存地址目录
                File filePath=new File(dirPath);
                if(!filePath.exists()) {//如果保存文件的地址不存在,就先创建目录
                    filePath.mkdirs();
                }
                String newname=name+"_"+UUID.randomUUID()+"_"+originalFilename;//用UUID重新命名,这是通用唯一识别码
                System.out.println("name="+name);
                System.out.println("originalFilename="+originalFilename);
                System.out.println("dirPath="+dirPath);
                System.out.println("newname="+newname);
                try {//使用MultipartFile接口的方法完成文件上传到指定位置
                    file.transferTo(new File(dirPath + newname));
                }catch (Exception e) {
                    e.printStackTrace();
                    return "error";
                }
            }
            System.out.println("will return success");
            return "success";
        }else 
            return "error";
    }
    
    
    @RequestMapping("/up")
    public String upjsp() {//通过MVC_03/up进入初始页面
        return "up";
    }
    
}

这里的文件上传到workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\MVC_03\upload


文件下载

1.导包

2.客户端页面要有一个超链接

<a href="${pageContext.request.contextPath }/download?filename=1.jpg">文件下载 </a>

需要先存在1.jpg这个文件,复制粘贴也好,文件上传进去的也好。

3.控制器类写一个方法下载文件(下面代码会有中文乱码问题)

@RequestMapping("/download")
    public ResponseEntity<byte[]> testDown(HttpServletRequest request,String filename) throws Exception{
        String path=request.getServletContext().getRealPath("/upload/");//指定要下载的文件所在的路径
        File file=new File(path+File.separator+filename);//创建该文件对象
        HttpHeaders headers=new HttpHeaders();//设置响应头
        headers.setContentDispositionFormData("attachment", filename);//通知浏览器以下载的方式打开文件
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.OK);
        
    }

 指定要下载名为filename的文件,HttpStatus.OK(200)表示协议状态,服务器已经成功处理请求。不能用Byte[],亦不解。

4.解决中文乱码问题

(1)在前端页面对编码统一,中文转UTF-8

<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8"%>
<%@page import="java.net.URLEncoder"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
     "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>下载页面</title>
</head>
<body>

    <a href="${pageContext.request.contextPath }/download?filename=<%=URLEncoder.encode("壁纸.jpg", "UTF-8")%>">
        中文名称文件下载 
    </a> 
</body>
</html>

第3行的URLEncoder是Servlet API提供的类。

第13行的encode(String s,String enc)方法是将前者的中文名转化为后者UTF-8编码。这里是先提供了一个壁纸.jpg的文件。

(2)后台控制器再把UTF-8转中文

//UTF-8转中文,写死的模板方法
    public String getFilename(HttpServletRequest request, String filename) throws Exception {
        // IE不同版本User-Agent中出现的关键词
        String[] IEBrowserKeyWords = { "MSIE", "Trident", "Edge" };
        // 获取请求头代理信息
        String userAgent = request.getHeader("User-Agent");
        for (String keyWord : IEBrowserKeyWords) {
            if (userAgent.contains(keyWord)) {
                //IE内核浏览器,统一为UTF-8编码显示
                return URLEncoder.encode(filename, "UTF-8");
            }
        }
        //火狐等其它浏览器统一为ISO-8859-1编码显示
        return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
    }
    

    @RequestMapping("/download")
    public ResponseEntity<byte[]> testDown(HttpServletRequest request, String filename) throws Exception {
        String path = request.getServletContext().getRealPath("/upload/");// 指定要下载的文件所在的路径
        File file = new File(path + File.separator + filename);// 创建该文件对象
        filename=this.getFilename(request, filename);
        HttpHeaders headers = new HttpHeaders();// 设置响应头
        headers.setContentDispositionFormData("attachment", filename);// 通知浏览器以下载的方式打开文件
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);
    }

相关推荐