spring實(shí)現(xiàn)單(多)文件上傳,列表顯示與下載

如題所言,這個(gè)project demo可以做到文件上傳到指定位置,然后在頁(yè)面上顯示這些圖片文件,每個(gè)圖片有一個(gè)下載按鈕,點(diǎn)擊后就可以將文件下載下來(lái)。首先來(lái)看下粗獷的頁(yè)面顯示。

導(dǎo)航頁(yè)面有三個(gè)連接,分別為單文件上傳,多文件上處與文件顯示,點(diǎn)擊文件顯示的時(shí)候便會(huì)出現(xiàn)上圖中的圖片列表,點(diǎn)擊圖片本身就會(huì)像一般的網(wǎng)頁(yè)那樣,在另一個(gè)頁(yè)面放大顯示出來(lái),點(diǎn)擊下載便會(huì)觸發(fā)下載功能,將文件下載?;镜墓δ芙榻B就結(jié)束了,接下來(lái)來(lái)看看具體的實(shí)現(xiàn)。

一、項(xiàng)目建立

首先使用idea,當(dāng)然eclipse也是OK的,建立一個(gè)maven項(xiàng)目,初學(xué)者可以在網(wǎng)上一搜便知。然后在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包導(dǎo)入后,接下來(lái)進(jìn)行第二個(gè)配置文件web.xml的配置,web.xml的主要作用便是設(shè)置過(guò)濾器,監(jiān)聽(tīng)器,為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處理字符轉(zhuǎn)換,servlet進(jìn)行服務(wù)配置。配置完web.xml后就可以處理最后一類配置文件,資源映射,數(shù)據(jù)庫(kù)配置,視圖解析,自動(dòng)注入與掃描等均在該配置文件中進(jìn)行配置,并在web.xml中注明其位置。本文中的<param-value>classpath:spring*.xml</param-value>便是指名為springxxx的xml文件,位置在默認(rèn)的資源文件夾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>

    <!-- 上傳文件的設(shè)置 ,maxUploadSize=-1,表示無(wú)窮大。uploadTempDir為上傳的臨時(shí)目錄 -->
    <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
          p:defaultEncoding="UTF-8"
          p:maxUploadSize="5400000"
          p:uploadTempDir="fileUpload/temp"/>
</beans:beans>

至此,所有的配置文件都配置好了,接下來(lái)就可以具體實(shí)施了。

二、前端頁(yè)面

首先來(lái)看下目錄結(jié)構(gòu),目錄結(jié)構(gòu)即邏輯,理解了邏輯后面的工作就容易進(jìn)行的多了。


在webapp下新建一個(gè)文件夾,筆者的為fileUpload用于上傳的文件的保存,新建的static中存放JQuery.js等靜態(tài)資源,注意這些文件夾在spring.xml中均進(jìn)行了映射設(shè)置,否則無(wú)法訪問(wèn),在WEB-INF下建立page文件夾,用于存放所需的頁(yè)面。
<1>index.jsp頁(yè)面
spring啟動(dòng)的初始頁(yè)面,中有三個(gè)鏈接,分別連接到后臺(tái),

<%@ 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>用戶上傳圖片頁(yè)面</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

</head>
<body>
    <div align="center">
        <a href="/file">一個(gè)文件上傳</a><br/>
        <a href="/files">多個(gè)文件上傳</a><br/>
        <a href="/show">文件列表</a><br/>
    </div>
</body>
</html>

當(dāng)點(diǎn)擊一個(gè)文件上傳的時(shí)候,進(jìn)入后臺(tái),后臺(tái)通過(guò)視圖解析器直接返回到上傳頁(yè)面

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

<2>afile.jsp頁(yè)面
為非常簡(jiǎn)單的單個(gè)文件上傳頁(yè)面

<%@ 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>

由此,邊將選中的文件傳遞給后臺(tái)了,后臺(tái)以二進(jìn)制字節(jié)碼的格式接收文件并將其寫入到指定位置。至于多文件上傳,對(duì)于前端,只是增加了幾個(gè)type為file的輸入框。
<3>showFiles.jsp圖片展示頁(yè)面
同樣,我們點(diǎn)擊index.jsp中的文件列表鏈接時(shí),直接將訪問(wèn)路徑傳入后臺(tái)對(duì)應(yīng)相應(yīng)的函數(shù),將獲取到的文件放入model里返回到showFiles.jsp中并顯示出來(lái)。

<%@ 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>下載文件顯示頁(yè)面</title>
    <script type="text/javascript">
        function showFile(name,downURL) {
            var path = "/images/"+name;
            var html = "<img alt='暫無(wú)圖片' 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>

對(duì)于放入model中的文件,通過(guò)標(biāo)簽將名為fileNameMap的文件集合中的文件遍歷出來(lái),對(duì)于每個(gè)文件,在后臺(tái)是以其名為key,路徑為value放入到map中,因此在前臺(tái)也需要以map取值得方式將其獲取,并將獲取到的文件名
通過(guò)剪切從而獲取到文件的真實(shí)名以顯示出來(lái)(由于在后臺(tái)為保障文件得唯一性,上傳文件的時(shí)候會(huì)用隨機(jī)UUID將其唯一命名)。由于前臺(tái)并不能直接通過(guò)絕對(duì)路徑訪問(wèn)到文件資源,因此需要用到映射路徑取訪問(wèn),對(duì)于一個(gè)文件的隱射路徑,在spring.xml中有定義,此處如上圖的path,在文件名(非剪切后的上傳名)前加"/images/"便是其訪問(wèn)路徑。至此,前端的文件便也完成了。

三、后臺(tái)功能實(shí)現(xiàn)代碼

由于不涉及到數(shù)據(jù)庫(kù),而且功能比較單一,因此只需要在java文件夾下新建一個(gè)controller層就可以了,其中新建一個(gè)FileController.java處理所有的功能。
<1>單文件處理

@RequestMapping("/onefile")
    public String oneFileUpload(@RequestParam("file") CommonsMultipartFile file, ModelMap model) {
        /**
         * 獲取原始文件名,定義一個(gè)新的唯一的文件名
         * 獲取文件的實(shí)際存儲(chǔ)位置與其映射存儲(chǔ)位置,為了安全,訪問(wèn)文件一般使用映射地址
         */
        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/";

        /**
         * 將文件以二進(jìn)制流的方式先讀取,在寫到實(shí)際存儲(chǔ)位置
         */
        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";
    }

多文件的處理只是在單文件的基礎(chǔ)上加了個(gè)循環(huán),進(jìn)行循環(huán)接收與寫入,當(dāng)然,是以數(shù)組的形式接收前臺(tái)傳遞過(guò)來(lái)的多文件。

@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>文件列表后臺(tái)處理過(guò)程
將獲取到的文件以鍵值對(duì)的形式放入map中,再將整個(gè)map傳到顯示頁(yè)面。

@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>下載過(guò)程處理
在列表顯示頁(yè)面,當(dāng)點(diǎn)擊對(duì)于照片的下載按鈕時(shí)便會(huì)將該照片的地址傳入后臺(tái),后臺(tái)通過(guò)該地址獲取到該照片并將其下載下來(lái)。

@RequestMapping("/down")
    public void downFile(HttpServletRequest request,HttpServletResponse response) {
//        String fileName = request.getParameter("fileName");
        String filePath = request.getParameter("filePath");
        try {
            //或者用絕對(duì)路徑但不建議 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 ;
            }

            // 設(shè)置響應(yīng)頭,控制瀏覽器下載該文件,不加該段則變?yōu)榱瞬榭?            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();
        }
    }

源碼鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,733評(píng)論 25 709
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,253評(píng)論 6 342
  • 初夏,午后,暖風(fēng)和煦,我走在路邊,感覺(jué)后背有細(xì)微的汗滴滲出,抬起頭看著陽(yáng)光透過(guò)翠綠的葉片投下斑駁的光影,感受這片刻...
    小紅兔子閱讀 311評(píng)論 0 2
  • 導(dǎo)入 由注釋回憶文學(xué)常識(shí):中國(guó)古代五大詩(shī)詞集《詩(shī)經(jīng)》《楚辭》《古詩(shī)十九首》《玉臺(tái)新詠》 看注釋。提示《文選》為中國(guó)...
    酒泉信天游閱讀 712評(píng)論 0 1

友情鏈接更多精彩內(nèi)容