美文网首页
spring实现单(多)文件上传,列表显示与下载

spring实现单(多)文件上传,列表显示与下载

作者: 竹凳子 | 来源:发表于2017-12-18 22:44 被阅读0次
    如题所言,这个project demo可以做到文件上传到指定位置,然后在页面上显示这些图片文件,每个图片有一个下载按钮,点击后就可以将文件下载下来。首先来看下粗犷的页面显示。

    导航页面有三个连接,分别为单文件上传,多文件上处与文件显示,点击文件显示的时候便会出现上图中的图片列表,点击图片本身就会像一般的网页那样,在另一个页面放大显示出来,点击下载便会触发下载功能,将文件下载。基本的功能介绍就结束了,接下来来看看具体的实现。

    一、项目建立

    首先使用idea,当然eclipse也是OK的,建立一个maven项目,初学者可以在网上一搜便知。然后在pom.xml依赖文件中假如如下的依赖:

    <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.freemarker</groupId>
          <artifactId>freemarker</artifactId>
          <version>2.3.21</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.0.1</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.2</version>
        </dependency>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.5</version>
        </dependency>
        <dependency>
          <groupId>taglibs</groupId>
          <artifactId>standard</artifactId>
          <version>1.1.2</version>
        </dependency>
    

    处理完依赖jar包导入后,接下来进行第二个配置文件web.xml的配置,web.xml的主要作用便是设置过滤器,监听器,为servlet命名,指定配置文件映射位置等。

        <filter>
            <filter-name>characterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
    
        <filter-mapping>
            <filter-name>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <servlet>
            <servlet-name>demoPro</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring*.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>demoPro</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    

    filter处理字符转换,servlet进行服务配置。配置完web.xml后就可以处理最后一类配置文件,资源映射,数据库配置,视图解析,自动注入与扫描等均在该配置文件中进行配置,并在web.xml中注明其位置。本文中的<param-value>classpath:spring*.xml</param-value>便是指名为springxxx的xml文件,位置在默认的资源文件夹resources下。本文使用的demo的文件名为spring.xml,具体配置如下。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/mvc"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:beans="http://www.springframework.org/schema/beans"
                 xmlns:context="http://www.springframework.org/schema/context"
                 xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/c"
                 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <annotation-driven />
    
        <resources mapping="/images/**" location="/fileUpload/img/" />
        <resources mapping="/page/**" location="/WEB-INF/page/"/>
        <resources mapping="/static/**" location="/static/" />
    
        <context:component-scan base-package="controller" />
        <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <beans:property name="prefix" value="/WEB-INF/page/" />
            <beans:property name="suffix" value=".jsp" />
        </beans:bean>
    
        <!-- 上传文件的设置 ,maxUploadSize=-1,表示无穷大。uploadTempDir为上传的临时目录 -->
        <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
              p:defaultEncoding="UTF-8"
              p:maxUploadSize="5400000"
              p:uploadTempDir="fileUpload/temp"/>
    </beans:beans>
    

    至此,所有的配置文件都配置好了,接下来就可以具体实施了。

    二、前端页面

    首先来看下目录结构,目录结构即逻辑,理解了逻辑后面的工作就容易进行的多了。


    在webapp下新建一个文件夹,笔者的为fileUpload用于上传的文件的保存,新建的static中存放JQuery.js等静态资源,注意这些文件夹在spring.xml中均进行了映射设置,否则无法访问,在WEB-INF下建立page文件夹,用于存放所需的页面。
    <1>index.jsp页面
    spring启动的初始页面,中有三个链接,分别连接到后台,
    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <title>用户上传图片页面</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    </head>
    <body>
        <div align="center">
            <a href="/file">一个文件上传</a><br/>
            <a href="/files">多个文件上传</a><br/>
            <a href="/show">文件列表</a><br/>
        </div>
    </body>
    </html>
    

    当点击一个文件上传的时候,进入后台,后台通过视图解析器直接返回到上传页面

        @RequestMapping("/file")
        public String file() {
            return "afile";
        }
    

    <2>afile.jsp页面
    为非常简单的单个文件上传页面

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <title>上传图片</title>
        <%--<base href="<%=basePath%>">--%>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    
        <form action="onefile" method="post" enctype="multipart/form-data" >
            <input type="file" name="file" />
            <input type="submit" value="上 传" />
        </form>
    </body>
    </html>
    

    由此,边将选中的文件传递给后台了,后台以二进制字节码的格式接收文件并将其写入到指定位置。至于多文件上传,对于前端,只是增加了几个type为file的输入框。
    <3>showFiles.jsp图片展示页面
    同样,我们点击index.jsp中的文件列表链接时,直接将访问路径传入后台对应相应的函数,将获取到的文件放入model里返回到showFiles.jsp中并显示出来。

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!DOCTYPE HTML>
    <html>
    <head>
        <script type="text/javascript" src="/static/jquery-3.2.1.js"></script>
    
        <title>下载文件显示页面</title>
        <script type="text/javascript">
            function showFile(name,downURL) {
                var path = "/images/"+name;
                var html = "<img alt='暂无图片' src="+path+"  width='180px' onclick='showFile(this)'/>";
                var picture = realName(name);
                html+=picture+"<a href="+downURL+">下载</a><br\>";
                $('#picture').append(html);
            }
    
            function showFile(obj) {
                window.location.href=obj.src;
            }
    
            function realName(key) {
                var arr = key.split("-");
                var name = arr[5];
                for(var i =6 ;i<arr.length;i++){
                    name = name+"-"+arr[i];
                }
                return name;
            }
        </script>
    
    </head>
    
    <body>
    <!-- 遍历Map集合 -->
    <c:forEach var="me" items="${fileNameMap}">
        <c:url value="/down" var="downURL">
            <c:param name="filePath" value="${me.value}"></c:param>
            <%--<c:param name="fileName" value="${me.key}"></c:param>--%>
        </c:url>
        <script type="text/javascript">
            $(function () {
                showFile('${me.key}','${downURL}');
            })
        </script>
    </c:forEach>
    </body>
    </html>
    

    对于放入model中的文件,通过标签将名为fileNameMap的文件集合中的文件遍历出来,对于每个文件,在后台是以其名为key,路径为value放入到map中,因此在前台也需要以map取值得方式将其获取,并将获取到的文件名
    通过剪切从而获取到文件的真实名以显示出来(由于在后台为保障文件得唯一性,上传文件的时候会用随机UUID将其唯一命名)。由于前台并不能直接通过绝对路径访问到文件资源,因此需要用到映射路径取访问,对于一个文件的隐射路径,在spring.xml中有定义,此处如上图的path,在文件名(非剪切后的上传名)前加"/images/"便是其访问路径。至此,前端的文件便也完成了。

    三、后台功能实现代码

    由于不涉及到数据库,而且功能比较单一,因此只需要在java文件夹下新建一个controller层就可以了,其中新建一个FileController.java处理所有的功能。
    <1>单文件处理

    @RequestMapping("/onefile")
        public String oneFileUpload(@RequestParam("file") CommonsMultipartFile file, ModelMap model) {
            /**
             * 获取原始文件名,定义一个新的唯一的文件名
             * 获取文件的实际存储位置与其映射存储位置,为了安全,访问文件一般使用映射地址
             */
            String fileName = file.getOriginalFilename();
            String newFileName = UUID.randomUUID()+"-"+fileName;
            String sc = "C:\\Users\\zhang\\GitHub\\spring\\spring_updownload\\src\\main\\webapp\\fileUpload\\img\\";
            String path = "/images/";
    
            /**
             * 将文件以二进制流的方式先读取,在写到实际存储位置
             */
            File f = new File(path);
            if(!f.exists())
                f.mkdir();
            if(!file.isEmpty()) {
                try {
                    FileOutputStream fos = new FileOutputStream(sc+newFileName);
                    InputStream in = file.getInputStream();
    
                    int b =0;
                    while((b=in.read())!=-1) {
                        fos.write(b);
                    }
    
                    fos.close();
                    in.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            return "redirect:index.jsp";
        }
    

    多文件的处理只是在单文件的基础上加了个循环,进行循环接收与写入,当然,是以数组的形式接收前台传递过来的多文件。

    @RequestMapping("/multiFiles")
        public String multiFiles (@RequestParam("file") CommonsMultipartFile[] files, HttpServletRequest request,ModelMap model) {
    
            List<String> list = new ArrayList<String>();
            String sc = "C:\\Users\\zhang\\GitHub\\spring\\spring_updownload\\src\\main\\webapp\\fileUpload\\img\\";
            String path = "/images/";
    
            File f = new File(path);
            if(!f.exists())
                f.mkdir();
    
            for(int i=0;i<files.length;i++) {
                String fileName = files[i].getOriginalFilename();
                String newFileName = UUID.randomUUID()+"-"+fileName;
    
                if(!files[i].isEmpty()) {
                    try {
                        FileOutputStream fos = new FileOutputStream(sc+newFileName);
                        InputStream in = files[i].getInputStream();
                        int b = 0;
                        while((b=in.read())!=-1) {
                            fos.write(b);
                        }
                        fos.close();
                        in.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                list.add(path + newFileName);
            }
            return "redirect:index.jsp";
        }
    

    <2>文件列表后台处理过程
    将获取到的文件以键值对的形式放入map中,再将整个map传到显示页面。

    @RequestMapping("/show")
        public String showFiles(ModelMap model) {
            String path = "C:\\Users\\zhang\\GitHub\\spring\\spring_updownload\\src\\main\\webapp\\fileUpload\\img\\";
            Map<String, File> fileNameMap = new HashMap<String, File>();
    
            File[] fileList = new File(path).listFiles();
            for(File file:fileList)
            {
                fileNameMap.put(file.getName(),file);
            }
            model.addAttribute("fileNameMap", fileNameMap);
            return "showFiles";
        }
    

    <3>下载过程处理
    在列表显示页面,当点击对于照片的下载按钮时便会将该照片的地址传入后台,后台通过该地址获取到该照片并将其下载下来。

    @RequestMapping("/down")
        public void downFile(HttpServletRequest request,HttpServletResponse response) {
    //        String fileName = request.getParameter("fileName");
            String filePath = request.getParameter("filePath");
            try {
                //或者用绝对路径但不建议 F:\IdeaProjects\spring_updownload\src\main\webapp\fileUpload\img\
    //            String path = "/images/";
                File file = new File(filePath);
    
                if(!file.exists()) {
                    request.setAttribute("message","下载资源已被删除");
                    System.out.println("download file is deleted!");
                    return ;
                }
    
                // 设置响应头,控制浏览器下载该文件,不加该段则变为了查看
                response.setHeader("content-disposition", "attachment;filename="
                        + URLEncoder.encode(filePath, "UTF-8"));
    
                /**
                 * 读取要下载的图片或者文件,将其放在缓冲中,再下载
                 */
                FileInputStream in = new FileInputStream(filePath);
                OutputStream out = response.getOutputStream();
                byte buffer[] = new byte[1024];
                int len = 0;
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
                in.close();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    源码链接

    相关文章

      网友评论

          本文标题:spring实现单(多)文件上传,列表显示与下载

          本文链接:https://www.haomeiwen.com/subject/exsuwxtx.html