zoukankan      html  css  js  c++  java
  • SpringMVC框架06——文件上传与下载

    1、文件上传

    Spring MVC框架的文件上传是基于commons-fileupload组件的文件上传,只不过Spring MVC框架在原有文件上传组件上做了进一步封装,简化了文件上传的代码实现。

    1.1、单文件上传

    需要commons-fileupload组件相关依赖

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>

     页面中的form表单上添加多部件属性,fileupload.jsp

    <form action="${pageContext.request.contextPath}/onefile" method="post" enctype="multipart/form-data">
        选择文件:<input type="file" name="myfile"><br>
        文件描述:<input type="text" name="description"><br>
        <input type="submit" value="上传">
    </form>

    enctype属性指定的是表单数据的编码方式,该属性有以下3个值:

    • application/x-www-form-urlencoded:默认的编码方式,只处理表单域里的value属性值;
    • multipart/form-data:以二进制流的方式来处理表单数据,并将文件域指定文件的内容封装到请求参数里;
    • text/plain:只有当表单的action属性为mailto:URL的形式时才使用,主要适用于直接通过表单发送邮件的方式。

    创建POJO实体类

    import org.springframework.web.multipart.MultipartFile;
    
    public class FileDomain {
        private String description;
        private MultipartFile myfile;
        
        //getter和setter
    }

    在实体类中声明MultipartFile类型的属性封装被上传的文件信息,属性名与文件上传页面fileupload.jsp中的file类型的表单参数名myfile相同。

    创建控制器类

    @Controller
    public class FileUploadController {
    
        @RequestMapping("/onefile")
        public String oneFileUpload(@ModelAttribute FileDomain fileDomain, HttpServletRequest request){
            //文件上传的位置
            String realpath = request.getServletContext().getRealPath("uploadfiles");
            //上传文件的名称
            String fileName = fileDomain.getMyfile().getOriginalFilename();
            File targetFile = new File(realpath,fileName);
            if(!targetFile.exists()){
                targetFile.mkdirs();//创建目录
            }
            try {
                fileDomain.getMyfile().transferTo(targetFile);
                System.out.println("文件上传成功");
            } catch (Exception e){
                e.printStackTrace();
            }
    
            return "showFile";
        }
    }

    配置springmvc.xml

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

    创建showFile.jsp用于展示结果:

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <head>
        <title>文件上传信息</title>
    </head>
    <body>
        文件名称:${fileDomain.myfile.originalFilename}<br>
        文件描述:${fileDomain.description}
    </body>
    </html>

    上传页面展示:

    上传结果展示:

    注意事项:

    • 在上传页面fileupload.jsp中,form表单一定要加enctype属性,值为multipart/form-data,表单提交方式设置为post;
    • form表单中的file标签的name属性要和实体类的MultipartFile属性的名称保持一致;
    • 要在springmvc.xml中使用CommonsMultipartResolver类配置multipartResolver用于文件上传;

    1.2、多文件上传

    创建multifiles.jsp文件上传页面:

    <form action="${pageContext.request.contextPath}/multifile" method="post" enctype="multipart/form-data">
        <p>
            选择文件1:<input type="file" name="myfile"><br>
            文件描述1:<input type="text" name="description">
        </p>
        <p>
            选择文件2:<input type="file" name="myfile"><br>
            文件描述2:<input type="text" name="description">
        </p>
        <p>
            选择文件3:<input type="file" name="myfile"><br>
            文件描述3:<input type="text" name="description">
        </p>
        <p>
            <input type="submit" value="提交">
        </p>
    </form>

    创建POJO类:

    public class MultiFileDomain {
        private List<String> description;
        private List<MultipartFile> myfile;
        //getter和setter
    }

    创建Controller类,接收上传参数:

    @Controller
    public class FileUploadController {
    
        //多文件上传
        @RequestMapping("/multifile")
        public String multiFileUpload(@ModelAttribute MultiFileDomain multiFileDomain,HttpServletRequest request){
            String realpath = request.getServletContext().getRealPath("uploadfiles");
            File targetDir = new File(realpath);
            if(!targetDir.exists()){
                targetDir.mkdirs();
            }
            List<MultipartFile> files = multiFileDomain.getMyfile();
            for (int i=0;i<files.size();i++){
                MultipartFile file = files.get(i);
                String fileName = file.getOriginalFilename();
                File targetFile = new File(realpath,fileName);
                //上传
                try {
                    file.transferTo(targetFile);
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            System.out.println("文件上传成功!");
            return "showMulti";
        }
    }

    创建成功信息页面showMulti.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>多文件上传结果</title>
    </head>
    <body>
        <table width="50%" border="1">
            <tr>
                <td>文件名</td>
                <td>详情</td>
            </tr>
            <c:forEach var="des" items="${multiFileDomain.description}" varStatus="loop">
                <tr>
                    <td>${multiFileDomain.myfile[loop.count-1].originalFilename}</td>
                    <td>${des}</td>
                </tr>
            </c:forEach>
        </table>
    </body>
    </html>

    测试多文件上传

    上传结果:

    2、文件下载

    2.1、文件下载相关介绍

    实现文件下载有两种方法:一种是通过超链接实现下载,另一种是利用程序编码实现下载。通过超链接实现下载比较简单,但是会暴露下载文件的真实位置,利用程序编码实现下载可以增加安全访问控制。
    利用程序实现下载需要设置两个报头:
    (1)设置Content-Type的值为application/x-msdownload
    这项设置主要是为了告诉浏览器,其所输出内容的类型不是普通文本文件或HTML文件,而是一个要保存到本地的下载文件。
    (2)设置Content-Disposition的值为attachment,并且在后面指定filename参数
    这项设置主要是让浏览器不要直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件中。该报头指定了接收程序处理数据内容的方式,在HTTP应用中只有attachment是标准方式,attachment表示要求用户干预。在attachment后面还可以指定filename参数,该参数是服务器建议浏览器将实体内容保存到文件中的文件名称。
    设置报头的示例代码如下:

    //设置下载文件使用的报头
    response.setHeader("Content-Type","application/x-msdownload");
    response.setHeader("Content-Disposition","attachment;filename="+filename);

    2.2、文件下载的功能实现

    创建FileDownController类,并编写下载功能的方法:

    @Controller
    public class FileDownController {
    
        @RequestMapping("/down")
        public String down(@RequestParam String filename, HttpServletRequest request, HttpServletResponse response){
            String filePath = null; //要下载的文件路径
            FileInputStream in = null; //输入流
            ServletOutputStream out = null; //输出流
            try {
                //文件下载路径
                filePath = request.getServletContext().getRealPath("uploadfiles");
                //设置下载文件使用的报头
                response.setHeader("Content-Type","application/x-msdownload");
                response.setHeader("Content-Disposition","attachment;filename="+toUTF8String(filename));
                //读入文件
                in = new FileInputStream(filePath+"\"+filename);
                //得到响应对象的输出流,用于向客户端输出二进制数据
                out = response.getOutputStream();
                out.flush();
                int aRead = 0;
                byte[] b = new byte[1024];
                while ((aRead=in.read(b))!=-1 && in!=null){
                    out.write(b,0,aRead);
                }
                out.flush();
                in.close();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("下载成功!");
            return null;
    
        }
    
        /**
         * 下载保存时中文文件名的字符编码转换方法
         */
        public String toUTF8String(String str){
            StringBuffer sb = new StringBuffer();
            int len = str.length();
            for (int i=0;i<len;i++) {
                //取出字符中的每个字符
                char c = str.charAt(i);
                //Unicode码值为0-255时,不做处理
                if(c>=0 && c<=255){
                    sb.append(c);
                }else{
                    //转换UTF-8编码
                    byte[] b;
                    try {
                        b = Character.toString(c).getBytes("UTF-8");
                    } catch (Exception e){
                        e.printStackTrace();
                        b = null;
                    }
                    //转换为%HH的字符串形式
                    for (int j=0;j<b.length;j++){
                        int k = b[j];
                        if(k<0){
                            k&=255;
                        }
                        sb.append("%"+Integer.toHexString(k).toUpperCase());
                    }
                }
            }
            return sb.toString();
        }
    
    }

    创建页面展示可下载文件的Controller类和方法:

    @RequestMapping("/show")
    public String show(HttpServletRequest request, Model model){
        //文件下载路径
        String realPath = request.getServletContext().getRealPath("uploadfiles");
        File dir = new File(realPath);
        File[] files = dir.listFiles();
        //获取该目录下的所有文件名
        ArrayList<String> fileNames = new ArrayList<String>();
        for (int i=0;i<files.length;i++) {
            fileNames.add(files[i].getName());
        }
        model.addAttribute("files",fileNames);
        return  "showDown";
    }

    创建用于文件下载展示的showDown.jsp页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>文件下载</title>
    </head>
    <body>
    
        <table width="50%" border="1">
            <tr>
                <th>文件名</th>
                <th>操作</th>
            </tr>
            <c:forEach var="filename" items="${files}">
                <tr>
                    <td>${filename} </td>
                    <td>
                        <a href="${pageContext.request.contextPath}/down?filename=${filename}">下载</a>
                    </td>
                </tr>
            </c:forEach>
        </table>
    
    </body>
    </html>

    效果展示:

    点击下载链接

  • 相关阅读:
    gcd
    主流浏览器对HTML5的兼容性
    Adobe与苹果之争落败:停止开发移动版Flash
    谷歌程序员年薪高达25万美元以上
    Delphi开发人员指南 第一部份快速开发的基础 第2章 Object Pascal 语言(二)
    Delphi开发人员指南 第一部份快速开发的基础 第2章 Object Pascal 语言(三)
    Delphi开发人员指南 第一部份快速开发的基础 第2章 Object Pascal 语言(一)
    2011年10月编程语言排行榜
    第一个Flash游戏,小到几乎看不出来是做什么的
    'release' is unavailable: not available in automatic reference counting mode
  • 原文地址:https://www.cnblogs.com/jpwz/p/10542814.html
Copyright © 2011-2022 走看看