SpringMVC(16)——文件下载

概述

实现文件下载有两种方法:一种是通过超链接实现下载,另一种是利用程序编码实现下载。通过超链接实现下载固然简单,但暴露了下载文件的真实位置,并且只能下载存放在Web应用程序所在的目录下的文件。利用程序编码实现下载可以增加安全访问控制,还可以从任意位置提供下载的数据,可以将文件存放到Web应用程序以外的目录中,也可以将文件保存到数据库中。

利用程序实现下载需要设置两个报头:

(1) Web服务器需要告诉浏览器其所输出内容的类型不是普通文本文件或HTML文件,而是一个要保存到本地的下载文件,这需要设置Content-Type的值为application/x-msdownload。

(2) Web服务器希望浏览器不直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件中,这需要设置Content-Disposition报头。该报头指定了接收程序处理数据内容的方式,在HTTP应用中只有attachment是标准方式,attachment表示要求用户干预。在attachment后面还可以指定filename参数,该参数是服务器建议浏览器将实体内容保存到文件中的文件名称。

设置报头的示例如下:

        response.setHeader("Content-Type","application/x-msdownload");
        response.setHeader("Content-Disposition","attachment;filename="+filename);

实例
创建springmvc项目并按照下图创建文件夹及文件

各文件内容如下:

FileDownController.java

package controller;

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 javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

@Controller
public class FileDownController {
    /**
     * 显示要下载的文件列表
     */
    @RequestMapping("/showDownFiles")
    public String showDownFiles(HttpServletRequest request, Model model) {
        String realPath = request.getServletContext().getRealPath("/fileUpload/temp/");
        System.out.println(realPath);
        File dir = new File(realPath);
        File[] files = dir.listFiles();
        // 获取该目录下的所有文件名
        ArrayList<String> fileNameList = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {
            System.out.println(files[i].getName());
            fileNameList.add(files[i].getName());
        }
        model.addAttribute("files", fileNameList);
        return "showDownFiles";
    }

    /**
     * 下载文件
     */
    @RequestMapping("/down")
    public String down(@RequestParam String filename, HttpServletRequest request, HttpServletResponse response) {
        try {
            // 要下载的文件路径
            String filePath = null;
            // 输入流
            FileInputStream fis = null;
            // 输出流
            ServletOutputStream sos = null;
            filePath = request.getServletContext().getRealPath("/fileUpload/temp/");
            // 设置下载文件使用的报头
            response.setHeader("Content-Type", "application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment;filename=" + toUTF8String(filename));
            // 读入文件
            fis = new FileInputStream(filePath + "\\" + filename);
            // 得到响应对象的输出流,用于向客户端输出二进制数据
            sos = response.getOutputStream();
            sos.flush();
            int aRead = 0;
            byte[] b = new byte[1024];
            while ((aRead = fis.read(b)) != -1 && fis != null) {
                sos.write(b, 0, aRead);
            }
            sos.flush();
            fis.close();
            sos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        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 (UnsupportedEncodingException 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();
    }
}

FileUploadController.java

package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import pojo.UploadFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;

@Controller
public class FileUploadController {
    /**
     * 多文件上传
     */
    @RequestMapping("/upload")
    public String upload(@ModelAttribute UploadFile uploadFile, HttpServletResponse response, HttpServletRequest request) {

        // 文件上传到服务器的位置"/fileUpload/temp/"
        String realPath = request.getServletContext().getRealPath("/fileUpload/temp/");
        System.out.println("文件所在位置:" + realPath);
        File targetDir=new File(realPath);
        if(!targetDir.exists()){
            targetDir.mkdirs();
        }
        List<MultipartFile> files=uploadFile.getMyfile();
        for (int i = 0; i < files.size(); i++) {
            MultipartFile multipartFile = files.get(i);
            String originalFilename = multipartFile.getOriginalFilename();
            File targetFile=new File(realPath,originalFilename);
            // 上传文件
            try {
                multipartFile.transferTo(targetFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "success";
    }
}

UploadFile.java

package pojo;

import org.springframework.web.multipart.MultipartFile;

import java.util.List;

public class UploadFile {
    // 声明一个MultipartFile类型的属性封装被上传的文件信息,属性名与文件选择页面index.jsp中的file类型的表单参数名myfile相同
    private List<MultipartFile> myfile;

    public List<MultipartFile> getMyfile() {
        return myfile;
    }

    public void setMyfile(List<MultipartFile> myfile) {
        this.myfile = myfile;
    }
}

showDownFiles.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>下载文件</title>
</head>
<body>
    <ul>
        <c:forEach items="${files}" var="filename">
            <li><a href="${pageContext.request.contextPath}/down?filename=${filename}">${filename}</a></li>
        </c:forEach>
    </ul>
</body>
</html>

success.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功</title>
</head>
<body>
<%--${uploadFile.myfile.originalFilename}等同于uploadFile.getMyfile().getOriginalFilename()--%>
<ul>
    <c:forEach items="${uploadFile.myfile}" var="file">
        <li style="color: red">${file.originalFilename}</li>
    </c:forEach>
</ul>
</body>
</html>

springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="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">

    <!-- 使用扫描机制,扫描包 -->
    <context:component-scan base-package="controller"/>

    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--使用Spring的CommonsMultipartResolver配置MultipartResolver用于文件上传-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8" p:maxUploadSize="5400000" p:uploadTempDir="fileUpload/temp">
        <!--defaultEncoding="utf-8"是请求的编码格式,默认是iso-8859-1;maxUploadSize="5400000"是允许上传文件的最大值,单位为字节;uploadTempDir="fileUpload/temp"为上传文件的临时路径-->
    </bean>
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!-- 避免中文乱码 -->
  <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>
</web-app>

index.jsp

<%@ 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>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
    选择文件1:<input type="file" name="myfile"><br>
    选择文件2:<input type="file" name="myfile"><br>
    选择文件3:<input type="file" name="myfile"><br>
    选择文件4:<input type="file" name="myfile"><br>
    选择文件5:<input type="file" name="myfile"><br>
    <input type="submit" value="上传文件">
</form>
</body>
</html>

运行程序效果如下:

地址:http://localhost:8080/showDownFiles

点击超链接下载文件

 

如果对完整源码有兴趣。

可搜索微信公众号【Java实例程序】或者扫描下方二维码关注公众号获取更多。

注意:在公众号后台回复【CSDN201911181543】可获取本节源码。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值