Springmvc之文件上传和下载
2018-10-07 本文已影响15人
爱撒谎的男孩
Springmvc之文件上传和下载
前提
- 在上传和下载之前需要在对应的根目录下创建对应的文件夹,比如我们在
webApp
下创建upload
文件夹下
添加依赖
commons-io
commons-fileupload
<!-- 添加文件上传的依赖 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
在配置文件中配置(spring-mvc.xml)
id
的名称一定是multipartResolver
,不能任意指定
<!-- 上传组件的解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件大小 -->
<property name="maxUploadSize" value="10000000"></property>
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"></property>
</bean>
制作上传表单
- 表单的提交方式一定为
POST
- 必须追加
enctype="multipart/form-data"
<form action="${pageContext.request.contextPath }/upload/upload.do" method="POST" enctype="multipart/form-data">
file: <input type="file" name="file" value="上传">
<br>
<input type="submit" value="上传">
</form>
完成controller
- 上传的参数一定为
MultipartFile file
@RequestMapping("/upload.do")
public String uplaod(MultipartFile file) throws IllegalStateException, IOException{
String fileName=file.getOriginalFilename(); //获取文件名
Long fileSize=file.getSize(); //获取文件大小
//上传 参数是文件上传后储存的路径,最终的文件上传后的文件路径为/home/chenjiabing/Documents/Blog/fileName
file.transferTo(new File("/home/chenjiabing/Documents/Blog",fileName));
//重定向到首页
return "redirect:../main/showIndex.do";
}
异步上传文件
定义表单
- 设置
onchange
事件,只要input的改变了,那么就上传文件
<input type="file" name="file" value="" id="iconPic" onchange="getImageFun()">
定义Controller
- 其中的参数最好定义映射关系
@RequestParam("file")
,否则有时候会出现不对应的情况 - 数据库中保存的文件的路径不需要保存项目路径,只需要保存项目的文件路径即可,比如
/upload/文件名
,那么我们使用http://localhost:8080/TeduStore/upload/文件名
就能访问到
@RequestMapping("/getImage.do")
@ResponseBody
public ResponseResult<Void> getImage(@RequestParam("file")MultipartFile file,HttpSession session) throws IllegalStateException, IOException{
ResponseResult<Void> result = new ResponseResult<Void>();
// 如果文件不为空
if (!file.isEmpty()) {
String originalFilename = file.getOriginalFilename(); // 获取初始的文件名称
UUID uuid = UUID.randomUUID();
// 使用随机算法生成文件名称,保证文件名称不冲突
String fileName = uuid.toString()
+ originalFilename.substring(originalFilename
.lastIndexOf("."));
// 获取文件在项目中的上传路径
String filePath = session.getServletContext().getRealPath(
"/upload/");
// 创建文件的存储路径
File f1 = new File(filePath, fileName);
// 判断项目中这个upload文件夹是否存在
if (!f1.getParentFile().exists()) {
f1.getParentFile().mkdirs(); // 创建
}
// 保存文件
try {
file.transferTo(f1);
// 存储到数据库中的路径
String fileToDatabase = "/upload/" + fileName;
Integer id=this.getId(session);
bloggerService.modifyImage(id, fileToDatabase);
result.setState(1);
result.setMessage("头像上传成功");
} catch (Exception e) {
result.setState(0);
result.setMessage("头像上传失败");
}
}
return result;
}
AJAx异步提交
- 必须设置
contentType:false
,processData:false
- 使用
FormData
对象保存数据,当然处理文件类型(File类型)的,我们也可以存储键值对,比如formdata.append("username","jack")
,最后一起提交即可
//上传文件的方法
function getImageFun(){
var file=document.getElementById("iconPic").files[0]; //获取当前的file
// 创建FormData对象
var formData=new FormData();
formData.append("file",file); //将文件放入formData中
$.ajax({
"url":"${pageContext.request.contextPath}/user/getImage.do",
"data":formData,
"type":"post",
"dataType":"json", //返回数据类型
"contentType":false, //不设置上传文件类型 ,因为上传的文件有多种类型的
"processData":false, //不处理数据
"success":function(obj){
alert(obj.message);
var url=window.URL.createObjectURL(file); //获取上传的的本地路径
$("#icon").attr("src",url); //将上面的头像显示为当前选择的图片
}
})
}
文件下载
第一种方式
- 直接在输入地址即可,比如:
http://localhost:8080/TeduStore/upload.do/download.do?fileName=1.jpg
/**
* 文件下载
* @param fileName 文件名
* @param request
* @throws IOException
*/
@RequestMapping("/download.do")
public ResponseEntity<byte[]> download(@RequestParam("fileName")String fileName,HttpServletRequest request) throws IOException{
//获取下载文件的路径,在文件中的真实路径
String path=request.getServletContext().getRealPath("/upload/");
//下载文件的全路径
File file=new File(path+File.separator+fileName);
HttpHeaders headers = new HttpHeaders();
//下载显示的文件名,解决中文名称乱码问题
String downloadFielName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");
//通知浏览器以attachment(下载方式)打开图片
headers.setContentDispositionFormData("attachment", downloadFielName);
//application/octet-stream : 二进制流数据(最常见的文件下载)。
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
headers, HttpStatus.CREATED);
}
第二种方式
-
controller
方法返回byte[]
- 使用
@ResponseBody
注解 - 设置请求头的
ContentType
类型为下载文件的类型 - 设置请求头的
ContentDisposition
下载图片
- 只需要在浏览器中输入 :
http://localhost:8080/Project/download/download.do?filename=1.png
.就会下载项目路径
下的文件夹upload
中文件
@RequestMapping("/download.do")
@ResponseBody
public byte[] download(HttpServletResponse response,HttpServletRequest request,String filename)
throws IOException {
// 转换编码格式为iso-8859-1
filename = URLEncoder.encode(filename, "utf-8");
// 设置响应头 contentType,这里是下载图片 因此写的是 image/png
response.setContentType("image/png");
// 设置响应头Content-Disposition,使用转义双引号
response.setHeader("Content-Disposition", "attachment;filename=\""
+ filename + "\"");
return getImage(filename, request);
}
/**
* 返回需要下载图片的byte数组
* @param filename 图片的名称
* @param request HttpServletRequest对象,需要获取下载图片的项目路径
* @return byte数组
* @throws IOException
*/
public byte[] getImage(String filename,HttpServletRequest request) throws IOException{
//获取图片文件存放的位置,在项目的upload文件夹下
String projectPath=request.getServletContext().getRealPath("/upload/");
//获取需要下载的图片的路径
File file=new File(projectPath+File.separator+filename);
//创建输入流,读取图片
InputStream inputStream=new FileInputStream(file);
//创建内存操作流
ByteArrayOutputStream out=new ByteArrayOutputStream();
byte[] b=new byte[1000]; //创建一个缓冲数组
int len=0;
//读取字节流,读入到byte数组中
while((len=inputStream.read(b))!=-1){
out.write(b,0,len); //写入byte数组输入流
}
inputStream.close();
out.close();
return out.toByteArray();
}
导出Excel
文件
- 改变请求头中的
contentTyp
e类型为excel
类型的即可
@RequestMapping("/export.do")
@ResponseBody
public byte[] export(HttpServletResponse response) throws IOException {
String filename="excel表格.xlsx";
// 转换编码格式为iso-8859-1
filename = URLEncoder.encode(filename, "utf-8");
// 设置响应头 contentType,这里是下载excel
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
// 设置响应头Content-Disposition
response.setHeader("Content-Disposition", "attachment;filename=\""
+ filename + "\"");
return createExcel();
}
//创建excel表格,变成byte数组
private byte[] createExcel() throws IOException{
//使用POI生成Excel
XSSFWorkbook workbook=new XSSFWorkbook(); //生成工作簿
XSSFSheet sheet = workbook.createSheet("第一张表"); //在工作簿中创建一个工作表
XSSFRow row = sheet.createRow(0); //创建行 行号从0开始
XSSFCell cell = row.createCell(0); //在行中创建单元格,从0开始,一行中包括多个单元格
cell.setCellValue("第一行第一个单元格"); //在单元格中添加数据
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
workbook.write(outputStream); //写入ByteOutputStream流中
workbook.close();
outputStream.close();
return outputStream.toByteArray();
}
导出数据库中的信息
- 我们可以使用上面的方式,将数据库中的信息写入到excel文件中,然后用户点击链接直接下载即可