Spring MVC 实现文件的上传和下载 (八)
完整的项目案例: springmvc.zip
目录
SpringMVC 中,文件的上传,是通过 MultipartResolver 实现的。 所以,如果要实现文件的上传,只要在 spring-mvc.xml 中注册相应的 MultipartResolver 即可。
MultipartResolver 的实现类有两个:
- CommonsMultipartResolver
- StandardServletMultipartResolver
两个的区别:
- 第一个需要使用 Apache 的 commons-fileupload 等 jar 包支持,但它能在比较旧的 servlet 版本中使用。
- 第二个不需要第三方 jar 包支持,它使用 servlet 内置的上传功能,但是只能在 Servlet 3 以上的版本使用。
第一个使用步骤:
/*CommonsMultipartResolver 上传用到的两个包*/ "commons-fileupload:commons-fileupload:1.3.1", "commons-io:commons-io:2.4"
如果是maven项目的话直接导入:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency> dispatcher-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:mvc="http://www.springframework.org/schema/mvc"
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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="edu.nf.ch08.controller"/> <mvc:annotation-driven/> <mvc:default-servlet-handler/>
<!-- 文件上传有两种方式,一种基于Servlet3.0的上传,一种基于
commons-upload上传,如果使用Servlet3.0的上传方式,可以
不需要配置MultipartResolver,Spring默认会注册一个
StandardServletMultipartResolver。只需要在web.xml中
启用<multipart-config>。
如果想使用commons-upload,那么需要配置一个CommonsMultipartResolver,
且指定bean的id为multipartResolver-->
<!-- 这里使用commons-upload-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 限制文件上传的总大小(单位:字节),不配置此属性默认不限制 -->
<property name="maxUploadSize" value="104857600"/>
<!-- 设置文件上传的默认编码-->
<property name="defaultEncoding" value="utf-8"/>
</bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"> <!-- 请求总控器 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> </web-app>
后台java(上传、下载)处理代码:
package edu.nf.ch08.controller; import org.apache.commons.io.FileUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder; /**
* @author wangl
* @date 2018/11/2
*/
@Controller
public class UploadController { /**
* 文件上传只需要Spring传入一个MultipartFile对象即可,
* 这个对象可以获取文件相关上传的信息。
* 一个MultipartFile表示单个文件上传,当需要上传多个文件时
* 只需要声明为MultipartFile[]数组即可。
* @return
*/
@PostMapping("/upload")
public ModelAndView upload(MultipartFile file){
//获取当前系统用户目录
String home = System.getProperty("user.home");
//指定上传的文件夹目录
File uploadDir = new File(home + "/files");
//如果目录不存在,则创建
if(!uploadDir.exists()){
uploadDir.mkdir();
}
//获取上传的文件名
String fileName = file.getOriginalFilename();
//构建一个完整的文件上传对象
File uploadFile = new File(uploadDir.getAbsolutePath() + "/" + fileName);
try {
//通过transferTo方法进行上传
file.transferTo(uploadFile);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
//将文件名存入Model,转发到index页面
ModelAndView mv = new ModelAndView("index");
mv.addObject("fileName", fileName);
return mv;
} /**
* 文件下载1
* 读取服务器本地文件并封装为ResponseEntity对象
* 响应客户端,ResponseEntity封装一个字节数组。
*
* 注意:如果文件很大,那么读入内存的字节数组就会很大,这时很容易引起内存溢出。
* 因此,这种方法不太适合下载大文件使用
* @param fileName 文件名
* @return
*/
@GetMapping("/download")
public ResponseEntity<byte[]> download(String fileName){
//依据文件名构建本地文件路径
String filePath = System.getProperty("user.home") + "/files/" + fileName;
//依据文件路径构建File对象
File file = new File(filePath);
//创建响应头对象,设置响应信息
HttpHeaders headers = new HttpHeaders();
try {
//对文件名进行重新编码,防止在响应头中出现中文乱码
String headerFileName = URLEncoder.encode(fileName,"UTF-8");
//设置响应内容处理方式为附件,并指定文件名
headers.setContentDispositionFormData("attachment", headerFileName);
//设置响应头类型为application/octet-stream,表示是一个流类型
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//将文件转换成字节数组
byte[] bytes = FileUtils.readFileToByteArray(file);
//创建ResponseEntity对象(封装文件字节数组、响应头、响应状态码)
ResponseEntity<byte[]> entity = new ResponseEntity<>(bytes, headers, HttpStatus.CREATED);
//最后将整个ResponseEntity对象返回给DispatcherServlet
return entity;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件下载失败");
}
} /**
* 文件下载2(主要解决下载大文件)
* 读取服务器本地文件并封装为ResponseEntity对象
* 响应客户端,ResponseEntity封装一个InputStreamResource
* @param fileName 文件名
* @return
*/
@GetMapping("/download2")
public ResponseEntity<InputStreamResource> download2(String fileName){
//依据文件名构建本地文件路径
String filePath = System.getProperty("user.home") + "/files/" + fileName;
//依据文件路径构建File对象
File file = new File(filePath);
//创建响应头对象,设置响应信息
HttpHeaders headers = new HttpHeaders();
try {
//对文件名进行重新编码,防止在响应头中出现中文乱码
String headerFileName = URLEncoder.encode(fileName,"UTF-8");
//设置响应内容处理方式为附件,并指定文件名
headers.setContentDispositionFormData("attachment", headerFileName);
//设置响应头类型为application/octet-stream,表示是一个流类型
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//打开一个输入流
InputStream inputStream = FileUtils.openInputStream(file);
//创建InputStreamResource封装输入流对象,用于读取服务器文件
InputStreamResource resource = new InputStreamResource(inputStream);
//创建ResponseEntity对象(InputStreamResource、响应头、响应状态码)
ResponseEntity<InputStreamResource> entity = new ResponseEntity<>(resource, headers, HttpStatus.CREATED);
//最后将整个ResponseEntity对象返回给DispatcherServlet
return entity;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件下载失败");
}
}
}
上传文件的网页html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>文件上传</h1>
<!-- 当有文件上传时,表单的enctype必须设置为multipart/form-data -->
<form method="post" action="upload" enctype="multipart/form-data">
File:<input type="file" name="file"/><br/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
上传成功后转发的jsp(下载文件)页面:
<%--
Created by IntelliJ IDEA.
User: wangl
Date: 2018/11/2
Time: 09:56
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="download2?fileName=${fileName}">${fileName}</a>
</body>
</html>
项目结构:
Spring MVC 实现文件的上传和下载 (八)的更多相关文章
- Spring MVC 实现文件的上传和下载
前些天一位江苏经贸的学弟跟我留言问了我这样一个问题:“用什么技术来实现一般网页上文件的上传和下载?是框架还是Java中的IO流”.我回复他说:“使用Spring MVC框架可以做到这一点,因为Spri ...
- 009 spring boot中文件的上传与下载
一:任务 1.任务 文件的上传 文件的下载 二:文件的上传 1.新建一个对象 FileInfo.java package com.cao.dto; public class FileInfo { pr ...
- 在SpringMVC框架下实现文件的 上传和 下载
在eclipse中的javaEE环境下:导入必要的架包 web.xml的配置文件: <?xml version="1.0" encoding="UTF-8" ...
- 文件的上传和下载--SpringMVC
文件的上传和下载是项目开发中最常用的功能,例如图片的上传和下载.邮件附件的上传和下载等. 接下来,将对Spring MVC环境中文件的上传和下载进行详细的讲解. 一.文件上传 多数文件上传都是通过表单 ...
- java实现ftp文件的上传与下载
最近在做ftp文件的上传与下载,基于此,整理了一下资料.本来想采用java自带的方法,可是看了一下jdk1.6与1.7的实现方法有点区别,于是采用了Apache下的框架实现的... 1.首先引用3个包 ...
- SecureCRT使用sz和rz命令进行文件的上传和下载
SecureCRT可以使用sz和rz命令进行文件的上传和下载. sz文件下载: 格式:sz 文件名称 即可将服务器的文件下载至本地. rz文件上传: 格式:rz 文件名称 即可将本地文件上传至服务器. ...
- 使用FTPClient进行文件服务器内文件的上传和下载
我用的FTPClient是由Apache组织的commons-net.jar包中的API,这个包用起来非常的方便,很容易上手.我在项目开发的过程中主要用到了文件的上传和下载功能,下面将我开发的代码贴出 ...
- iOS开发中文件的上传和下载功能的基本实现-备用
感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传 ...
- Apache FtpServer 实现文件的上传和下载
1 下载需要的jar包 Ftp服务器实现文件的上传和下载,主要依赖jar包为: 2 搭建ftp服务器 参考Windows 上搭建Apache FtpServer,搭建ftp服务器 3 主要代码 在ec ...
随机推荐
- 2014--My Plan
写于2014/1/10 从2014年开始我每年规划自己的life,每年10个plans. 回忆2013: 2013年,改变了很多.准确的说,那10个月,像个漫长的旅程,像个人生的转折点,应该可以这么说 ...
- C#系列之聊聊.Net Core的InMemoryCache
作者:暴王 个人博客:http://www.boydwang.com/2017/12/net-core-in-memory-cache/ 这两天在看.net core的in memory cache, ...
- Perl:undef类型和defined()函数
undef和defined()函数 undef表示的像是数据库中的"null".它表示空,啥也没有,是完全未定义的.这不等于字符串的空,不等于数值0,它是另一种类型. 在某些时候, ...
- 02.SQLServer性能优化之---水平分库扩展
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 第一次引入文件组的概念:http://www.cnblogs.com/dunitian/ ...
- C#线程同步--限量使用
问题抽象:当某一资源同一时刻允许一定数量的线程使用的时候,需要有个机制来阻塞多余的线程,直到资源再次变得可用.线程同步方案:Semaphore.SemaphoreSlim.CountdownEvent ...
- sqlserver count(1),count(*),count(列名) 详解
sqlserver数据库 count(1),count(*),count(列名) 的执行区别 count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL count(1)包括 ...
- Linq To Xml操作XML增删改查
对XML文件的操作在平时项目中经常要运用到,比如用于存放一些配置相关的内容:本文将简单运用Linq TO Xml对XML进行操作,主要讲解对XML的创建.加载.增加.查询.修改以及删除:重点在于类XD ...
- OKR20180607
OKR---目标与关键成果法 一套明确和跟踪目标及其完成情况的管理工具和方法 OKR的主要目标是明确公司和团队的“目标”以及每个目标达成的可衡量的“关键结果”. “目标”是设定一个定性的时间目标.“关 ...
- vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值。
vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值. vue 父组件与子组件相互通信 一.父组件给子组件传值 props 实现父组件向子组件传值. 1父组件里: ...
- [PHP] 算法-字符串的左循环的PHP实现
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=”abcXYZde ...