SpringBoot学习笔记(十一:使用MongoDB存储文件 ) 您所在的位置:网站首页 mongodb储存图片 SpringBoot学习笔记(十一:使用MongoDB存储文件 )

SpringBoot学习笔记(十一:使用MongoDB存储文件 )

#SpringBoot学习笔记(十一:使用MongoDB存储文件 )| 来源: 网络整理| 查看: 265

@

目录一、MongoDB存储文件1、MongoDB存储小文件2、MongoDB存储大文件2.1、GridFS存储原理2.2、GridFS使用2.2.1、使用shell命令2.2.2、使用API二、SpringBoot整合MongoDB存储文件1、MongoDB存储小文件1.1、添加依赖1.2、配置1.3、模型层1.4、持久层1.5、服务层1.6、控制层1.7、工具类1.8、前端页面1.9、运行效果2、MongoDB存储大文件2.1、依赖2.2、启动类2.3、配置2.4、实体类2.5、服务层2.6、控制层2.7、运行效果

感谢各位的阅读。博主的这篇文章只是博主的学习笔记,有些问题博主也不太清楚,所以没有解答,抱歉。 源码比较乱,大家将就着看:https://gitee.com/fighter3/dairly-learn.git

一、MongoDB存储文件 1、MongoDB存储小文件

MongoDB是一个面向文档的数据库,使用BSON(Binary JSON:二进制JSON)格式来存储数据。

BSON格式

在这里插入图片描述

BSON支持在一个文档中最多存储16MB的二进制数据。如果存储的是小于16M的文件,可以直接将文件转换为二进制数据,以文档形式存入集合。

Java中文件和二进制转换也比较简单:

文件转换为byte数组 public static byte[] fileToByte(File file) throws IOException{ byte[] bytes = null; FileInputStream fis = null; try{ fis = new FileInputStream(file); bytes = new bytes[(int) file.length()]; fis.read(bytes); }catch(IOException e){ e.printStackTrace(); throw e; }finally{ fis.close(); } return bytes; } byte数组转换为文件 public static void bytesToFile(byte[] bFile, String fileDest) { FileOutputStream fileOuputStream = null; try { fileOuputStream = new FileOutputStream(fileDest); fileOuputStream.write(bFile); } catch (IOException e) { e.printStackTrace(); } finally { if (fileOuputStream != null) { try { fileOuputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }

如果是实现文件下载功能,可以把字节码直接写进流中。

2、MongoDB存储大文件

MongoDB单个文档的存储限制是16M,如果要存储大于16M的文件,就要用到MongoDB GridFS。

GridFS是Mongo的一个子模块,使用GridFS可以基于MongoDB来持久存储文件。并且支持分布式应用(文件分布存储和读取)。作为MongoDB中二进制数据存储在数据库中的解决方案,通常用来处理大文件。

GridFS不是MongoDB自身特性,只是一种将大型文件存储在MongoDB的文件规范,所有官方支持的驱动均实现了GridFS规范。GridFS制定大文件在数据库中如何处理,通过开发语言驱动来完成、通过API接口来存储检索大文件。

2.1、GridFS存储原理

GridFS使用两个集合(collection)存储文件。一个集合是chunks, 用于存储文件内容的二进制数据;一个集合是files,用于存储文件的元数据。

GridFS会将两个集合放在一个普通的buket中,并且这两个集合使用buket的名字作为前缀。MongoDB的GridFs默认使用fs命名的buket存放两个文件集合。因此存储文件的两个集合分别会命名为集合fs.files ,集合fs.chunks。

当把一个文件存储到GridFS时,如果文件大于chunksize (每个chunk块大小为256KB),会先将文件按照chunk的大小分割成多个chunk块,最终将chunk块的信息存储在fs.chunks集合的多个文档中。然后将文件信息存储在fs.files集合的唯一一份文档中。其中fs.chunks集合中多个文档中的file_id字段对应fs.files集中文档”_id”字段。

读文件时,先根据查询条件在files集合中找到对应的文档,同时得到“_id”字段,再根据“_id”在chunks集合中查询所有“files_id”等于“_id”的文档。最后根据“n”字段顺序读取chunk的“data”字段数据,还原文件。

GridFS存储过程

在这里插入图片描述

fs.files 集合存储文件的元数据,以类json格式文档形式存储。每在GridFS存储一个文件,则会在fs.files集合中对应生成一个文档。

fs.files集合中文档的存储内容

在这里插入图片描述

fs.chunks 集合存储文件文件内容的二进制数据,以类json格式文档形式存储。每在GridFS存储一个文件,GridFS就会将文件内容按照chunksize大小(chunk容量为256k)分成多个文件块,然后将文件块按照类json格式存在.chunks集合中,每个文件块对应fs.chunk集合中一个文档。一个存储文件会对应一到多个chunk文档。

fs.chunks集合中文档的存储内容

在这里插入图片描述

2.2、GridFS使用 2.2.1、使用shell命令

mongoDB提供mingofiles工具,可以使用命令行来操作GridFS。其实有四个主要命令,分别为:

put —存储命令 get —获取命令 list —列表命令 delete —删除命令

操作实例:

存储文件 向数据库中存储文件的格式:mongofiles -d 数据库名字 -l "要上传的文件的完整路径名" put "上传后的文件名"

在这里插入图片描述 在filetest数据库中就会多出2个集合,它们存储了GridFS文件系统的所有文件信息,查询这两个集合就能看到上传的文件的一些信息:

在这里插入图片描述

列出文件 查看GridFS文件系统中所有文件:mongofiles -d 数据库名字 list

在这里插入图片描述

获取文件 从GridFS文件系统中下载一个文件到本地:mongofiles -d 数据库名字 -l "将文件保存在本地的完整路径名" get "GridFS文件系统中的文件名" ,如果不写-l以及后面的路径参数,则保存到当前位置。

在这里插入图片描述

删除文件 删除GridFS文件系统中的某个文件:mongofiles -d 数据库名字 delete " 文件名 "

在这里插入图片描述

2.2.2、使用API

MongoDB支持多种编程语言驱动。比如c、java、C#、nodeJs等。因此可以使用这些语言MongoDB驱动API操作,扩展GridFS。

以Java为例:

依赖包和版本: org.mongodb:3.2.2 mongo-java-driver:3.2.2

公共方法

public MongoDatabase mongoDatabase() throws Exception{ MongoClient mongoClient = new MongoClient(mongoHost, mongoPort); return mongoClient.getDatabase(dbName); } 上传文件 @Test public void upload() throws Exception { // 获取文件流 File file = new File("E:/zookeeper-3.4.8.tar.gz"); InputStream in = new FileInputStream(file); // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 上传 ObjectId fileId = bucket.uploadFromStream(UUID.randomUUID().toString(), in); System.out.println("上传完成。 文件ID:"+fileId); } 查找文件 @Test public void findOne() throws Exception { // 获取文件ID String objectId = "57fbaffcec773716ecc54ef4"; // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 获取内容 GridFSFindIterable gridFSFindIterable = bucket.find(Filters.eq("_id", new ObjectId(objectId))); GridFSFile gridFSFile = gridFSFindIterable.first(); System.out.println("filename: " + gridFSFile.getFilename()); } 下载文件 @Test public void download() throws Exception { // 获取文件ID String objectId = "57fbaffcec773716ecc54ef4"; // 获取文件流 File file = new File("D:/zookeeper-3.4.8.tar.gz"); // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 创建输出流 OutputStream os = new FileOutputStream(file); // 下载 bucket.downloadToStream(new ObjectId(objectId), os); System.out.println("下载完成。"); } 删除文件 @Test public void delete() throws Exception { // 获取文件ID String objectId = "57fbaffcec773716ecc54ef4"; // 创建一个容器,传入一个`MongoDatabase`类实例db GridFSBucket bucket = GridFSBuckets.create(mongoDatabase()); // 删除 bucket.delete(new ObjectId(objectId)); System.out.println("删除完成。"); } 二、SpringBoot整合MongoDB存储文件

MongoDB可以将文件直接存储在文档或者通过GridFS存储大文件,这里同样进行SpringBoot整合MongoDB的两种实现。

1、MongoDB存储小文件

SpringBoot整合MongoDB将文件以文档形式直接存入集合,和普通的MongDB存储区别不大。

1.1、添加依赖 spring-boot-starter-data-mongodb:用来操作MongoDB spring-boot-starter-thymeleaf:前端页面采用thymeleaf模板 org.springframework.boot spring-boot-starter-data-mongodb org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-web 1.2、配置 server.address=localhost server.port=8081 # thymeleaf配置,开发环境不启用缓存,正式环境下请启用缓存,提高性能 spring.thymeleaf.cache=false # thymeleaf对html元素格式要求严格,设置它的mode为HTML,忘记结束标签后不会报错 spring.thymeleaf.mode=HTML # 编码 spring.http.encoding. spring.http.encoding.enabled=true # MongoDB 配置 # 连接url spring.data.mongodb.uri=mongodb://test:test@localhost:27017/filetest # 文件上传限制 spring.servlet.multipart.max-file-size=30MB spring.servlet.multipart.max-request-size=50MB 1.3、模型层

文件模型类:

/** * @Author 三分恶 * @Date 2020/1/11 * @Description 文档类 */ @Document public class FileModel { @Id // 主键 private String id; private String name; // 文件名称 private String contentType; // 文件类型 private long size; private Date uploadDate; private String md5; private Binary content; // 文件内容 private String path; // 文件路径 /** *省略getter/setter */ protected FileModel() { } public FileModel(String name, String contentType, long size, Binary content) { this.name = name; this.contentType = contentType; this.size = size; this.content = content; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof FileModel)) return false; FileModel fileModel = (FileModel) o; return size == fileModel.size && Objects.equals(id, fileModel.id) && Objects.equals(name, fileModel.name) && Objects.equals(contentType, fileModel.contentType) && Objects.equals(uploadDate, fileModel.uploadDate) && Objects.equals(md5, fileModel.md5) && Objects.equals(content, fileModel.content) && Objects.equals(path, fileModel.path); } @Override public int hashCode() { return Objects.hash(id, name, contentType, size, uploadDate, md5, content, path); } } 1.4、持久层

采用MongoRepository的方式操作MongoDB,只需在接口里继承MongoRepository,就可以调用MongoRepository的内置方法。

public interface FileRepository extends MongoRepository { } 1.5、服务层

服务层接口:

public interface FileService { /** * 保存文件 */ FileModel saveFile(FileModel file); /** * 删除文件 */ void removeFile(String id); /** * 根据id获取文件 */ Optional getFileById(String id); /** * 分页查询,按上传时间降序 * @return */ List listFilesByPage(int pageIndex, int pageSize); }

服务层实现类:

@Service public class FileServiceImpl implements FileService { @Autowired private FileRepository fileRepository; @Override public FileModel saveFile(FileModel file) { return fileRepository.save(file); } @Override public void removeFile(String id) { fileRepository.deleteById(id); } @Override public Optional getFileById(String id) { return fileRepository.findById(id); } @Override public List listFilesByPage(int pageIndex, int pageSize) { Page page = null; List list = null; Sort sort = Sort.by(Sort.Direction.DESC,"uploadDate"); Pageable pageable = PageRequest.of(pageIndex, pageSize, sort); page = fileRepository.findAll(pageable); list = page.getContent(); return list; } } 1.6、控制层 @Controller public class FileController { @Autowired private FileService fileService; @Value("${server.address}") private String serverAddress; @Value("${server.port}") private String serverPort; @RequestMapping(value = "/") public String index(Model model) { // 展示最新二十条数据 model.addAttribute("files", fileService.listFilesByPage(0, 20)); return "index"; } /** * 分页查询文件 */ @GetMapping("files/{pageIndex}/{pageSize}") @ResponseBody public List listFilesByPage(@PathVariable int pageIndex, @PathVariable int pageSize) { return fileService.listFilesByPage(pageIndex, pageSize); } /** * 获取文件片信息 */ @GetMapping("files/{id}") @ResponseBody public ResponseEntity serveFile(@RequestParam("id") String id) throws UnsupportedEncodingException { Optional file = fileService.getFileById(id); if (file.isPresent()) { return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=" + new String(file.get().getName().getBytes("utf-8"),"ISO-8859-1")) .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream") .header(HttpHeaders.CONTENT_LENGTH, file.get().getSize() + "").header("Connection", "close") .body(file.get().getContent().getData()); } else { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not fount"); } } /** * 在线显示文件 */ @GetMapping("/view") @ResponseBody public ResponseEntity serveFileOnline(@RequestParam("id") String id) { Optional file = fileService.getFileById(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().getData()); } else { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not fount"); } } /** * 上传 */ @PostMapping("/") public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { try { FileModel f = new FileModel(file.getOriginalFilename(), file.getContentType(), file.getSize(), new Binary(file.getBytes())); f.setMd5(MD5Util.getMD5(file.getInputStream())); fileService.saveFile(f); System.out.println(f); } catch (IOException | NoSuchAlgorithmException ex) { ex.printStackTrace(); redirectAttributes.addFlashAttribute("message", "Your " + file.getOriginalFilename() + " is wrong!"); return "redirect:/"; } redirectAttributes.addFlashAttribute("message", "You successfully uploaded " + file.getOriginalFilename() + "!"); return "redirect:/"; } /** * 上传接口 */ @PostMapping("/upload") @ResponseBody public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file) { FileModel returnFile = null; try { FileModel f = new FileModel(file.getOriginalFilename(), file.getContentType(), file.getSize(), new Binary(file.getBytes())); f.setMd5(MD5Util.getMD5(file.getInputStream())); returnFile = fileService.saveFile(f); String path = "//" + serverAddress + ":" + serverPort + "/view/" + returnFile.getId(); return ResponseEntity.status(HttpStatus.OK).body(path); } catch (IOException | NoSuchAlgorithmException ex) { ex.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage()); } } /** * 删除文件 */ @GetMapping("/delete") @ResponseBody public ResponseEntity deleteFile( @RequestParam("id") String id) { try { fileService.removeFile(id); return ResponseEntity.status(HttpStatus.OK).body("DELETE Success!"); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); } } } 1.7、工具类

md5工具类:

public class MD5Util { /** * 获取该输入流的MD5值 */ public static String getMD5(InputStream is) throws NoSuchAlgorithmException, IOException { StringBuffer md5 = new StringBuffer(); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] dataBytes = new byte[1024]; int nread = 0; while ((nread = is.read(dataBytes)) != -1) { md.update(dataBytes, 0, nread); }; byte[] mdbytes = md.digest(); // convert the byte to hex format for (int i = 0; i < mdbytes.length; i++) { md5.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); } return md5.toString(); } } 1.8、前端页面

前端页面index.html:

文件服务 首页 上传文件: 文件列表 文件名 文件ID contentType 文件大小 上传时间 md5 操作 没有文件信息!! 预览|删除 body{ text-align: center; } table{ margin: auto; } 1.9、运行效果 上传文件:

在这里插入图片描述

在这里插入图片描述

预览 在这里插入图片描述

下载

在这里插入图片描述

删除 在这里插入图片描述

在文件的操作过程中,可以通过可视化工具或shell来查看存储在MongoDB中的文件:

可以看到,在fileModel集合中存储了我们上传的文件,文件的内容是以二进制的形式存储

在这里插入图片描述

2、MongoDB存储大文件

Spring Data MongoDB提供了GridFsOperations接口以及相应的实现GridFsTemplate,可以和GridFs交互。

这里在上一个工程的基础上进行改造。

2.1、依赖

和上一个工程相比,这里添加开源工具包hutool的依赖:

cn.hutool hutool-all 4.5.1 2.2、启动类 @SpringBootApplication public class SpringbootFileGridfsApplication { public static void main(String[] args) { SpringApplication.run(SpringbootFileGridfsApplication.class, args); } //Tomcat large file upload connection reset @Bean public TomcatServletWebServerFactory tomcatEmbedded() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol< ?>)) { //-1 means unlimited ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(-1); } }); return tomcat; } }

TomcatServletWebServerFactory() ⽅法主要是为了解决上传文件较大时出现连接重置的问题,这个异常后台是捕捉不到的:

在这里插入图片描述

2.3、配置 application.properties # MongoDB 配置 # 连接uri #spring.data.mongodb.uri=mongodb://test:test@localhost:27017/filetest spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=filetest spring.data.mongodb.username=test spring.data.mongodb.password=test # 文件上传限制 spring.servlet.multipart.max-file-size=1020MB spring.servlet.multipart.max-request-size=1020MB 配置类 /** * @Author 三分恶 * @Date 2020/1/11 * @Description */ @Configuration public class MongoConfig { //获取配置文件中数据库信息 @Value("${spring.data.mongodb.database}") String db; ////GridFSBucket用于打开下载流 @Bean public GridFSBucket getGridFSBucket(MongoClient mongoClient){ MongoDatabase mongoDatabase = mongoClient.getDatabase(db); GridFSBucket bucket = GridFSBuckets.create(mongoDatabase); return bucket; } } 2.4、实体类 文件实体类 /** * @Author 三分恶 * @Date 2020/1/11 * @Description */ @Document public class FileDocument { @Id // 主键 private String id; private String name; // 文件名称 private long size; // 文件大小 private Date uploadDate; // 上传时间 private String md5; // 文件MD5值 private byte[] content; // 文件内容 private String contentType; // 文件类型 private String suffix; // 文件后缀名 private String description; // 文件描述 private String gridfsId; // 大文件管理GridFS的ID /** * 省略getter、setter、equales、hashCode、toString方法 */ } 接口结果实体类 ** * @Author 三分恶 * @Date 2020/1/11 * @Description 公用数据返回模型 */ public class ResponseModel { public static final String Success = "success"; public static final String Fail = "fail"; private String code = "fail"; private String message = ""; private String data; //私有构造函数,此类不允许手动实例化,需要调用getInstance()获取实例 private ResponseModel() { } /** * 返回默认的实例 * @return */ public static ResponseModel getInstance() { ResponseModel model = new ResponseModel(); model.setCode(ResponseModel.Fail); return model; } /** *省略getter/setter */ } 2.5、服务层

上一个实例里采用MongReposity来操作MongoDB,这里操作MongoDB采用MongoTemplate,操作GridFs采用GridFsTemplate。

/** * @Author 三分恶 * @Date 2020/1/11 * @Description */ @Service public class FileServiceImpl implements FileService { @Autowired private MongoTemplate mongoTemplate; @Autowired private GridFsTemplate gridFsTemplate; @Autowired private GridFSBucket gridFSBucket; /** * 保存文件 * @param file * @return */ @Override public FileDocument saveFile(FileDocument file) { file = mongoTemplate.save(file); return file; } /** * 上传文件到Mongodb的GridFs中 * @param in * @param contentType * @return */ @Override public String uploadFileToGridFS(InputStream in , String contentType){ String gridfsId = IdUtil.simpleUUID(); //将文件存储进GridFS中 gridFsTemplate.store(in, gridfsId , contentType); return gridfsId; } /** * 删除文件 * @param id */ @Override public void removeFile(String id) { //根据id查询文件 FileDocument fileDocument = mongoTemplate.findById(id , FileDocument.class ); if(fileDocument!=null){ //根据文件ID删除fs.files和fs.chunks中的记录 Query deleteFileQuery = new Query().addCriteria(Criteria.where("filename").is(fileDocument.getGridfsId())); gridFsTemplate.delete(deleteFileQuery); //删除集合fileDocment中的数据 Query deleteQuery=new Query(Criteria.where("id").is(id)); mongoTemplate.remove(deleteQuery,FileDocument.class); } } /** * 根据id查看文件 * @param id * @return */ @Override public Optional getFileById(String id){ FileDocument fileDocument = mongoTemplate.findById(id , FileDocument.class ); if(fileDocument != null){ Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(fileDocument.getGridfsId())); try { //根据id查询文件 GridFSFile fsFile = gridFsTemplate.findOne(gridQuery); //打开流下载对象 GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId()); if(in.getGridFSFile().getLength() > 0){ //获取流对象 GridFsResource resource = new GridFsResource(fsFile, in); //获取数据 fileDocument.setContent(IoUtil.readBytes(resource.getInputStream())); return Optional.of(fileDocument); }else { fileDocument = null; return Optional.empty(); } }catch (IOException ex){ ex.printStackTrace(); } } return Optional.empty(); } /** * 分页列出文件 * @param pageIndex * @param pageSize * @return */ @Override public List listFilesByPage(int pageIndex, int pageSize) { Query query = new Query().with(Sort.by(Sort.Direction.DESC, "uploadDate")); long skip = (pageIndex -1) * pageSize; query.skip(skip); query.limit(pageSize); Field field = query.fields(); field.exclude("content"); List files = mongoTemplate.find(query , FileDocument.class ); return files; } } 2.6、控制层

控制层变动不大,主要是调用服务层方法的返回值和参数有变化:

@Controller public class FileController { @Autowired private FileService fileService; @Value("${server.address}") private String serverAddress; @Value("${server.port}") private String serverPort; @RequestMapping(value = "/") public String index(Model model) { // 展示最新二十条数据 model.addAttribute("files", fileService.listFilesByPage(0, 20)); return "index"; } /** * 分页查询文件 */ @GetMapping("files/{pageIndex}/{pageSize}") @ResponseBody public List listFilesByPage(@PathVariable int pageIndex, @PathVariable int pageSize) { return fileService.listFilesByPage(pageIndex, pageSize); } /** * 获取文件片信息 */ @GetMapping("files/{id}") @ResponseBody public ResponseEntity serveFile(@PathVariable String id) throws UnsupportedEncodingException { Optional file = fileService.getFileById(id); if (file.isPresent()) { return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=" + new String(file.get().getName().getBytes("utf-8"),"ISO-8859-1")) .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 fount"); } } /** * 在线显示文件 */ @GetMapping("/view") @ResponseBody public ResponseEntity serveFileOnline(@RequestParam("id") String id) { Optional file = fileService.getFileById(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") .header(HttpHeaders.CONTENT_LENGTH , file.get().getSize() + "") .body(file.get().getContent()); } else { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not found"); } } /** * 上传 */ @PostMapping("/") public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { try { FileDocument fileDocument = new FileDocument(); fileDocument.setName(file.getOriginalFilename()); fileDocument.setSize(file.getSize()); fileDocument.setContentType(file.getContentType()); fileDocument.setUploadDate(new Date()); String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")); fileDocument.setSuffix(suffix); fileDocument.setMd5(MD5Util.getMD5(file.getInputStream())); //将文件存入gridFs String gridfsId = fileService.uploadFileToGridFS(file.getInputStream() , file.getContentType()); fileDocument.setGridfsId(gridfsId); fileDocument = fileService.saveFile(fileDocument); System.out.println(fileDocument); } catch (IOException | NoSuchAlgorithmException ex) { ex.printStackTrace(); redirectAttributes.addFlashAttribute("message", "Your " + file.getOriginalFilename() + " is wrong!"); return "redirect:/"; } redirectAttributes.addFlashAttribute("message", "You successfully uploaded " + file.getOriginalFilename() + "!"); return "redirect:/"; } /** * 上传接口 */ @PostMapping("/upload") @ResponseBody public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file) { FileDocument returnFile = null; try { FileDocument fileDocument = new FileDocument(); fileDocument.setName(file.getOriginalFilename()); fileDocument.setSize(file.getSize()); fileDocument.setContentType(file.getContentType()); fileDocument.setUploadDate(new Date()); String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")); fileDocument.setSuffix(suffix); fileDocument.setMd5(MD5Util.getMD5(file.getInputStream())); //将文件存入gridFs String gridfsId = fileService.uploadFileToGridFS(file.getInputStream() , file.getContentType()); fileDocument.setGridfsId(gridfsId); returnFile = fileService.saveFile(fileDocument); String path = "//" + serverAddress + ":" + serverPort + "/view/" + returnFile.getId(); return ResponseEntity.status(HttpStatus.OK).body(path); } catch (IOException | NoSuchAlgorithmException ex) { ex.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage()); } } /** * 删除文件 */ @GetMapping("/delete") @ResponseBody public ResponseModel deleteFile( @RequestParam("id") String id) { ResponseModel model = ResponseModel.getInstance(); if(!StrUtil.isEmpty(id)){ fileService.removeFile(id); model.setCode(ResponseModel.Success); model.setMessage("删除成功"); }else { model.setMessage("请传入文件id"); } return model; } }

前端页面没有变动。 2.7、运行效果

上传文件 这里我们选择一个比较大的mp4文件 在这里插入图片描述在这里插入图片描述

预览 预览还存在问题,后台会报错:org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class edu.hpu.domain.ResponseModel] with preset Content-Type 'video/mp4' 待解决

在这里插入图片描述

下载 在这里插入图片描述

删除 在这里插入图片描述

在上传和删除数据的过程中,可以通过可视化工具或shell来查看MongoDB中的数据

fileDocment中的数据:fileDocment是一个普通的集合,对应地以文档的形式存储了FileDocument实例

在这里插入图片描述

fs.files中的数据:文件的元数据 在这里插入图片描述

fs.chunks中的数据:file被切分成若干个chunks,存储了文件的二进制数据 在这里插入图片描述

本文为学习笔记类博客,学习资料来源见参考!

【1】:MongoDB GridFS 【2】:Mongodb的文件存储GridFs 【3】:MongoDB学习笔记(五) MongoDB文件存取操作 【4】:《MongoDB大数据权威处理指南》 【5】:java文件转二进制 【6】:Java将文件转为字节数组 【7】:java文件下载的几种方式 【8】:文件和byte数组之间相互转换 【9】:关于知名数据库MongoDB,有个功能你不可不知! 【10】:MongoDB 学习笔记(五):固定集合、GridFS文件系统与服务器端脚本 【11】:GridFS 基于 MongoDB 的分布式文件存储系统 【12】:SpringBoot Mongodb文件存储服务器 【13】:MongoDB文件服务器搭建 【14】:基于 MongoDB 及 Spring Boot 的文件服务器的实现 【15】:SpringBoot中使用GridFS 【16】:SpringBoot2.x集成mongoDB4.0实现音频文件的上传下载功能 【17】:10.18. GridFS Support 【18】:GridFS in Spring Data MongoDB 【19】:纯洁的微笑 《精通SpringBoot 42讲》 【20】:JAVA 应用 / hutool / hutool系列教材 (一)- 介绍 - 简介



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有