1、下载MongoDb
https://www.mongodb.com/try/download/community
安装很简单、基本都是下一步。安装好需要进行环境变量的配置、在path里面吧对应的bin路径加入到里面D:\mongodb-win32-x86_64-2012plus-4.2.23\bin
2、集成
配置YML
spring:
data:
mongodb:
host: localhost
port: 27017
database: test
加入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
新建FileDocument实体类
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.util.Date;
@Document
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class FileDocument implements Serializable {
/**
* id
*/
private String id;
/**
* 文件名称
*/
private String name;
/**
* 文件大小
*/
private long size;
/**
* 上传时间
*/
private Date uploadDate;
/**
* 文件的md5值
*/
private String md5;
/**
* 文件内容
*/
private byte[] content;
/**
* 文件类型
*/
private String contentType;
/**
* 文件后缀
*/
private String suffix;
/**
* 文件描述
*/
private String description;
/**
* 大文件管理GridFS的ID
*/
private String gridfsId;
}
新建FileService、FileServiceImpl服务类实现类
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.result.DeleteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Field;
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.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Service
public class FileServiceImpl_1 implements FileService_1 {
private static String collectionName = "fileDate";
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private GridFsTemplate gridFsTemplate;
@Autowired
private GridFSBucket gridFSBucket;
/**
* 表单上传附件
*
* @param md5
* @param file
* @return
*/
@Override
public FileDocument saveFile(String md5, MultipartFile file) {
//已存在该文件,则实现秒传
FileDocument fileDocument = getByMd5(md5);
if (fileDocument != null) {
return fileDocument;
}
fileDocument = new FileDocument();
fileDocument.setName(file.getOriginalFilename());
fileDocument.setSize(file.getSize());
fileDocument.setContentType(file.getContentType());
fileDocument.setUploadDate(new Date());
fileDocument.setMd5(md5);
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
fileDocument.setSuffix(suffix);
try {
//文件存入gridfs
String gridfsId = uploadFileToGridFS(file.getInputStream(), file.getContentType());
fileDocument.setGridfsId(gridfsId);
//fileDocument.setContent();
//上传的信息保存在mongodb
fileDocument = mongoTemplate.save(fileDocument, collectionName);
} catch (IOException ex) {
ex.printStackTrace();
}
return fileDocument;
}
/**
* 上传文件到Mongodb的GridFs中
*
* @param in
* @param contentType
* @return
*/
private String uploadFileToGridFS(InputStream in, String contentType) {
String gridfsId = UUID.randomUUID().toString();
//文件,存储在GridFS中
gridFsTemplate.store(in, gridfsId, contentType);
return gridfsId;
}
/**
* 删除附件
*
* @param id 文件id
* @param isDeleteFile 是否删除文件
*/
@Override
public void removeFile(String id, boolean isDeleteFile) {
FileDocument fileDocument = mongoTemplate.findById(id, FileDocument.class, collectionName);
if (fileDocument != null) {
Query query = new Query().addCriteria(Criteria.where("_id").is(id));
DeleteResult result = mongoTemplate.remove(query, collectionName);
System.out.println("result:" + result.getDeletedCount());
if (isDeleteFile) {
Query deleteQuery = new Query().addCriteria(Criteria.where("filename").is(fileDocument.getGridfsId()));
gridFsTemplate.delete(deleteQuery);
}
}
}
/**
* 查询附件
*
* @param id 文件id
* @return
* @throws IOException
*/
@Override
public Optional<FileDocument> getById(String id) {
FileDocument fileDocument = mongoTemplate.findById(id, FileDocument.class, collectionName);
if (fileDocument != null) {
Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(fileDocument.getGridfsId()));
try {
GridFSFile fsFile = gridFsTemplate.findOne(gridQuery);
GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId());
if (in.getGridFSFile().getLength() > 0) {
GridFsResource resource = new GridFsResource(fsFile, in);
fileDocument.setContent(inputStreamToByte(resource.getInputStream()));
return Optional.of(fileDocument);
} else {
fileDocument = null;
return Optional.empty();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return Optional.empty();
}
/**
* 流转换成byte数组
*
* @param inStream
* @return
* @throws IOException
*/
private byte[] inputStreamToByte(InputStream inStream) throws IOException {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
//buff用于存放循环读取的临时数据
byte[] buff = new byte[100];
int rc = 0;
while ((rc = inStream.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
return swapStream.toByteArray();
}
/**
* 根据md5获取文件对象
*
* @param md5
* @return
*/
@Override
public FileDocument getByMd5(String md5) {
Query query = new Query().addCriteria(Criteria.where("md5").is(md5));
return mongoTemplate.findOne(query, FileDocument.class, collectionName);
}
/**
* 文件分页
*
* @param pageIndex
* @param pageSize
* @return
*/
@Override
public List<FileDocument> listFilesByPage(int pageIndex, int pageSize) {
Sort sort = Sort.by(Sort.Order.desc("uploadDate"));
Query query = new Query().with(sort);
long skip = (pageIndex - 1) * pageSize;
query.skip(skip);
query.limit(pageSize);
Field field = query.fields();
field.exclude("content");
List<FileDocument> files = mongoTemplate.find(query, FileDocument.class, collectionName);
return files;
}
}
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Optional;
public interface FileService_1 {
/**
* 保存信息的文件
*
* @param md5
* @param file
* @return
*/
public FileDocument saveFile(String md5, MultipartFile file);
/**
* 移除文件
*
* @param id
* @param isDeleteFile
*/
public void removeFile(String id, boolean isDeleteFile);
/**
* 根据id查询附件
*
* @param id
* @return
*/
public Optional<FileDocument> getById(String id);
/**
* 根据md5获取文件对象
*
* @param md5
* @return
*/
public FileDocument getByMd5(String md5);
/**
* 文件分页
*
* @param pageIndex
* @param pageSize
* @return
*/
public List<FileDocument> listFilesByPage(int pageIndex, int pageSize);
}
在这里需要注意了@Autowired
private GridFSBucket gridFSBucket;这个导入的时候可能报错、这时候我们需要做初始化配置。增加MongoConfig类
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MongoConfig {
@Value("${spring.data.mongodb.database}")
String db ;
@Bean
public GridFSBucket getGridFSBucket(MongoClient mongoClient){
MongoDatabase database = mongoClient.getDatabase(db);
GridFSBucket gridFSBucket = GridFSBuckets.create(database);
return gridFSBucket ;
}
}
Controller类
/**
* 上传文件列表
*
* @param pageIndex
* @param pageSize
* @return
*/
@RequestMapping("/list")
public List<FileDocument> list(int pageIndex, int pageSize) {
return fileService_1.listFilesByPage(pageIndex, pageSize);
}
/**
* 查询返回值\在线打开
*
* @param id 文件id
* @return
*/
@GetMapping("/viewFile")
public ResponseEntity<Object> serveFileOnlines(String id) {
Optional<FileDocument> file = fileService_1.getById(id);
if (file.isPresent()) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "fileName=" + file.get().getName())
.header(HttpHeaders.CONTENT_TYPE, file.get().getContentType())
.header(HttpHeaders.CONTENT_LENGTH, file.get().getSize() + "").header("Connection", "close")
.body(file.get().getContent());
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not found");
}
}
/**
* 下载文件
*
* @param id
* @return
* @throws UnsupportedEncodingException
*/
@GetMapping("/down")
public ResponseEntity<Object> downloadFileById(String id) throws UnsupportedEncodingException {
Optional<FileDocument> file = fileService_1.getById(id);
if (file.isPresent()) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=" + URLEncoder.encode(file.get().getName(), "utf-8"))
.header(HttpHeaders.CONTENT_TYPE, "application/octet-stream")
.header(HttpHeaders.CONTENT_LENGTH, file.get().getSize() + "").header("Connection", "close")
.body(file.get().getContent());
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not found");
}
}
/**
* 表单上传文件
* 当数据库中存在该md5值时,可以实现秒传功能
*
* @param file 文件
* @return
*/
@PostMapping("/upload")
public JSONObject formUpload(@RequestParam("file") MultipartFile file) {
JSONObject json = new JSONObject();
try {
if (file != null && !file.isEmpty()) {
String fileMd5 = getMD5(file.getInputStream());
FileDocument fileDocument = fileService_1.saveFile(fileMd5, file);
System.out.println(fileDocument);
json.put("code","1");
json.put("msg","上传成功");
json.put("date",fileDocument.getId());
} else {
json.put("code","0");
json.put("msg","请上传文件");
json.put("date","");
}
} catch (IOException e) {
json.put("code","-1");
json.put("msg","上传失败");
json.put("date","");
} catch (Exception e) {
json.put("code","-1");
json.put("msg","上传失败");
json.put("date","");
}
return json;
}
/**
* 删除附件
*
* @param id
* @return
*/
@GetMapping("/delete")
public JSONObject deleteFileByGetMethod(String id) {
JSONObject json = new JSONObject();
if (id != null) {
fileService_1.removeFile(id, true);
json.put("code",1);
json.put("msg","删除成功");
json.put("date","");
} else {
json.put("code",0);
json.put("msg","删除失败");
json.put("date","");
}
return json;
}
/**
* 流转换成MD5字符串
*
* @param inputStream
* @return
*/
private String getMD5(InputStream inputStream) {
BigInteger md5 = null;
try {
byte[] buffer = inputStreamToByte(inputStream);
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(buffer, 0, buffer.length);
byte[] b = md.digest();
md5 = new BigInteger(1, b);
} catch (NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
}
assert md5 != null;
return md5.toString(16);
}
/**
* 流转换成byte数组
*
* @param inStream
* @return
* @throws IOException
*/
private byte[] inputStreamToByte(InputStream inStream) throws IOException {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
//buff用于存放循环读取的临时数据
byte[] buff = new byte[100];
int rc = 0;
while ((rc = inStream.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
return swapStream.toByteArray();
}