文件的上传下载在web项目上经常用到,之前都是用别人写好的代码。工作之余自己也尝试写了上传下载的接口,以后项目中用到的话可以直接拿来用。本实例是在mysql上记录上传的文件信息,所以需要一个实体类。废话不多说,直接上菜:
1.开发环境:IDEA+JDK8+SpringBoot2.2.2+MongoDB
2.首先在pom文件引入MongoDB的依赖包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
3.配置文件连接设置(我用的是本地的MongoDB没有设置用户名和密码):
data:
mongodb:
uri: mongodb://127.0.0.1:27017/test
servlet:
multipart:
#是否支持批量上传
enabled: true
#上传文件最大为 100M
max-file-size: 100MB
#上传总数据大小 200M
max-request-size: 200MB
4.实体类FileMetadata创建:
package com.example.demo.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.persistence.*;
import java.sql.Timestamp;
/**
* 保存在mongo中的文件,与各个相关实体比如申请工单、协议等关联
*/
@Data
@Entity
@Table(name = "file_metadata")
public class FileMetadata {
@Id
// 这应该不是数据库生成,而是mongo那边的ID
// @GeneratedValue(generator = "uuidMongoFiles")
// @GenericGenerator(name = "uuidMongoFiles", strategy = "uuid")
@Column(name = "id", columnDefinition = "varchar(128) COMMENT '编号'")
private String id;
@Column(name = "FILE_TYPE", columnDefinition = "varchar(20) COMMENT '文件类型,如资质文件、协议文件等'")
private String fileType;
@Column(name = "OBJECT_ID", columnDefinition = "varchar(128) COMMENT '关联的ID'")
private String associateId;
@Column(name = "OBJECT_CLASS", columnDefinition = "varchar(20) COMMENT '关联的实体类型'")
private String associateObjectClass;
@Column(name = "FILE_SEQ_NO", columnDefinition = "SMALLINT COMMENT '文件顺序'")
private Integer fileOrder;
@Column(name = "FILE_ORIGIN_NAME", columnDefinition = "varchar(255) COMMENT '上传文件原名'")
private String fileOriginName;
@Column(name = "FILE_DISPLAY_NAME", columnDefinition = "varchar(255) COMMENT '文件的标准展示名'")
private String fileDisplayName;
@Column(name = "FILE_YEAR", columnDefinition = "SMALLINT COMMENT '资料相关的年份'")
private Integer year;
@Column(name = "UPLOAD_TIME", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间'")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp uploadTime;
@Column(name = "MEMO", columnDefinition = "varchar(255) COMMENT '备注信息'")
private String comment;
@Column(name = "OPERATOR", columnDefinition = "varchar(50) COMMENT '操作员'")
private String operator;
@Transient
private String viewPtah;
}
5.保存到MongoDB上的文件信息实体类创建:
package com.example.demo.mongodb.entity;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 定义保存在mongoFile中的mongoData
*/
@Data
public class MongoFileMetaDate {
private String fileName;
private String relatedOrgId;
private String uploadUser;
private LocalDateTime uploadTime;
private String comment;
}
6.Controller层代码实现:
package com.example.demo.controller;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.dao.FileMetadataRepo;
import com.example.demo.entity.FileMetadata;
import com.example.demo.mongodb.repo.MongoFileRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.Timestamp;
import java.time.LocalDateTime;
/**
* @Author: lqs
* @Date: 2019/12/30 15:01
*/
@RestController
@RequestMapping("/uploadFiles")
public class uploadFilesController {
@Autowired
private MongoFileRepo mongoFileRepo;
@Autowired
private FileMetadataRepo fileMetadataRepo;
/**
* 文件上传
* @param file
* @return
*/
@RequestMapping("/upload")
@ResponseBody
public String httpUpload(@RequestParam("files") MultipartFile file){
JSONObject object=new JSONObject();
String comment = "上传文件测试";//备注
FileMetadata fileMetadata = new FileMetadata();
fileMetadata.setAssociateId("10086");
fileMetadata.setUploadTime(Timestamp.valueOf(LocalDateTime.now()));//上传时间
fileMetadata.setFileOrder(1);//排序
fileMetadata.setComment(comment);
fileMetadata.setYear(2019);//年份
fileMetadata.setFileOriginName(file.getOriginalFilename());//文件名
fileMetadata.setOperator("会飞的鱼");//操作人
// 下面这三个应该是什么?
fileMetadata.setFileType(null);
fileMetadata.setFileDisplayName(null);
fileMetadata.setAssociateObjectClass(null);
try{
String id = mongoFileRepo.saveFile(file, comment);
fileMetadata.setId(id);
fileMetadataRepo.save(fileMetadata);
object.put("result","文件上传成功");
}catch (Exception e){
object.put("result","文件失败");
}
return object.toString();
}
/**
* 文件下载
* @param id
* @param response
* @param request
* @throws Exception
*/
@RequestMapping("/downLoad")
@ResponseBody
public void downLoad(String id, HttpServletResponse response, HttpServletRequest request) throws Exception{
mongoFileRepo.getFileById(id,response,request);
}
}
7.Repo层实现:
package com.example.demo.mongodb.repo;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.mongodb.entity.MongoFileMetaDate;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDateTime;
@Repository
public class MongoFileRepo {
private final GridFsTemplate fsTemplate;
private final MongoDbFactory mongoDbFactory;
public MongoFileRepo(GridFsTemplate fsTemplate,MongoDbFactory mongoDbFactory) {
this.fsTemplate = fsTemplate;
this.mongoDbFactory = mongoDbFactory;
}
/**
* 向MongoDB中保存一个文件,返回其ID
*/
public String saveFile(InputStream inputStream, MongoFileMetaDate metaDate) {
ObjectId objectId = fsTemplate.store(inputStream, metaDate.getFileName(), metaDate);
return objectId.toString();
}
/**
* 向MongoDB中保存一个文件,返回其ID
*/
public String saveFile(MultipartFile file, String comment) {
JSONObject object=new JSONObject();
try (InputStream inputStream = file.getInputStream()) {
MongoFileMetaDate metaDate = new MongoFileMetaDate();
metaDate.setFileName(file.getOriginalFilename());
metaDate.setComment(comment);
metaDate.setRelatedOrgId("");
metaDate.setUploadTime(LocalDateTime.now());
metaDate.setUploadUser("");
return saveFile(inputStream, metaDate);
} catch (Exception e) {
object.put("fail","上传失败!");
return object.toString();
}
}
/**
* 通过上传时生成的id来下载文件
* @param id
* @param response
* @param request
* @throws Exception
*/
public void getFileById(String id, HttpServletResponse response, HttpServletRequest request) throws Exception {
System.out.println("Finding by ID: " + id);
GridFSFile fsFile = fsTemplate.findOne(new Query(Criteria
.where("_id").is(new ObjectId(id))));
//打开下载流对象
MongoDatabase db = mongoDbFactory.getDb();
GridFSBucket gridFSBucket = GridFSBuckets.create(db);
GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(fsFile.getObjectId());
//创建GridFsResource用于获取流对象
GridFsResource resource = new GridFsResource(fsFile, gridFSDownloadStream);
String fileName = fsFile.getFilename().replace(",", "");
//处理中文文件名乱码
if (request.getHeader("User-Agent").toUpperCase().contains("MSIE") ||
request.getHeader("User-Agent").toUpperCase().contains("TRIDENT")
|| request.getHeader("User-Agent").toUpperCase().contains("EDGE")) {
fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
} else {
//非IE浏览器的处理:
fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
}
// 通知浏览器进行文件下载
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
IOUtils.copy(resource.getInputStream(), response.getOutputStream());
}
}
总结:本文只写了两个接口,可以用postman进行上传测试,下载的话直接在浏览器输入地址即可:http://127.0.0.1:8080/uploadFiles/downLoad?id=5e09c46d08a8862e7cd682a7
本次分享就到这里,如有纰漏,敬请指正。