上传文件的基本要求:
1、form表单提交必须是post请求:method="post"
2、添加enctype属性:enctype="multipart/form-data"
好了,接下来开始进入正题
1、首先创建一个JSP用于提交文件
regist.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
2、在SpringMVC的配置文件中添加文件上传的解析器
spring-mvc.xml
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxUploadSize" value="-1"/>
bean>
3、编写Controller代码
文件上传的目的地可以是数据库,也可以是磁盘。但是一般不建议放到数据库中,数据量大时会增加数据库的负担。有条件的以单独使用一台服务器来存储流媒体。
这里上传成功之后直接返回一个JSON类型的数据,告知上传成功。
@RequestMapping(value="/regist", method= {RequestMethod.GET, RequestMethod.POST})
public @ResponseBody String regist(@RequestParam MultipartFile file,Student student) {
try {
// 上传到本地
// 获取文件名
String fileName = file.getOriginalFilename();
String headPath = "D://" + fileName;
File dest = new File(headPath);
// 获取文件的二进制数组
byte[] bytes = file.getBytes();
// 上传到数据库
student.setHead(bytes);
// 把数据封装到对象中
student.setHeadPath(headPath);
studentService.regist(student);
// 把文件写到磁盘
file.transferTo(dest);
return "文件:" + fileName + "上传成功!";
} catch (Exception e) {
e.printStackTrace();
return "文件上传失败!";
}
}
4、实体类
public class Student{
private Integer id;
private String name;
private String pass;
private String sex;
private Integer age;
private String email;
private String birthday;
private byte[] head; // 头像的二进制数据
private String headPath;// 头像的路径
// 省略set/get方法
}
5、service
// 接口
public int regist(Student student);
// 实现类
public int regist(Student student) {
return studentMapper.regist(student);
}
6、dao
// 接口
public int regist(Student student);
7、dao映射文件
mybatis默认可以省略入参的类型,所以这里没有写parameterType;
insert默认的返回值就是int类型,所以这里也没有写resultType;
<insert id="regist">
insert into student
(id, name, pass, age, sex, email,birthday, head)
values
(seq_stu.nextval, #{name, jdbcType=VARCHAR}, #{pass, jdbcType=VARCHAR}, #{age, jdbcType=VARCHAR},
#{sex, jdbcType=VARCHAR}, #{email, jdbcType=VARCHAR}, to_date(#{birthday, jdbcType=DATE},'yyyy-mm-dd'),
#{head, jdbcType=VARBINARY})
insert>
下载的原理:通过ServletOutputStream将byte类型的数据响应到浏览器的过程。
下载的基本要求:
设置头信息:
content-disposition
attachement;filename=name
1、编写Controllerd代码
这里提供两种解决方案:
(1)使用ResponseEntity
因为在上传的时候写了直接把图片存储到数据库的操作,所以这边写了两种获取方式:
1)直接从数据库读取图片信息。
2)从数据库读取图片的路径,根据图片路径构造File对象。下面dao接口中会提到查询图片路径的方法。
@RequestMapping(value="/download" , method= {RequestMethod.GET, RequestMethod.POST})
public ResponseEntity<byte[]> download(Student student) throws Exception {
// 通过数据库查询文件的byte[]
// byte[] head = studentService.getHead(student);
// 查询数据库获取文件路径
String headPath = studentService.getHeadPath(student);
// 构建文件对象
File file = new File(headPath);
// 读取文件
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
// 设置头信息
HttpHeaders hh = new HttpHeaders();
hh.setContentDispositionFormData("attachement", "a.jpg");
// 返回ResponseEntity对象
// 第一个参数:要下载的文件的byte数组
// 第二个参数:头信息,因为HttpHeaders实现了MultiValueMap这个接口
// 第三个参数:http状态,一般请求成200,所以要写HttpStatus.OK
return new ResponseEntity<byte[]>(bytes, hh, HttpStatus.OK);
}
(2)使用ServletOutputStream
@RequestMapping(value="/download1" , method= {RequestMethod.GET, RequestMethod.POST})
public void download1(Student student, HttpServletResponse resp) throws Exception {
// 查询数据库获取文件路径
String headPath = studentService.getHeadPath(student);
// 构建文件对象
File file = new File(headPath);
// 输入流读取文件
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
// 设置头信息
resp.setContentType("multipart/form-data");
resp.setHeader("content-disposition", "attachement;filename=b.jpg");
// 相应到浏览器
ServletOutputStream outputStream = resp.getOutputStream();
// 将二进制数组写到输出流中
outputStream.write(bytes);
outputStream.flush();
// 关闭流
outputStream.close();
}
2、service
// 接口
public byte[] getHead(Student student);
public String getHeadPath(Student student);
// 实现类
public byte[] getHead(Student student) {
return (byte[]) studentMapper.getHead(student);
}
public String getHeadPath(Student student) {
return studentMapper.getHeadPath(student);
}
3、dao
需要注意的是,service的接口中返回值类型是byte[],dao中接口的返回值类型必须是Object,否则会报错。
// 查询图片
public Object getHead(Student student);
// 查询图片路径
public String getHeadPath(Student student);
4、映射文件
注意byte[]类型的写法是:[B,写成byte[]会报类型转换错误。报错信息里也让写成[B
<select id="getHead" resultType="[B">
select head from student where id = #{id, jdbcType=INTEGER}
select>
<select id="getHeadPath" resultType="String">
select headPath from student where id = #{id, jdbcType=INTEGER}
select>