概述
实现文件下载有两种方法:一种是通过超链接实现下载,另一种是利用程序编码实现下载。通过超链接实现下载固然简单,但暴露了下载文件的真实位置,并且只能下载存放在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实例程序】或者扫描下方二维码关注公众号获取更多。
注意:在公众号后台回复【优快云201911181543】可获取本节源码。