前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MongodbGFS存储大文件(java版)

MongodbGFS存储大文件(java版)

作者头像
林老师带你学编程
发布2019-05-25 21:13:08
1.8K0
发布2019-05-25 21:13:08
举报
文章被收录于专栏:强仔仔强仔仔

Mongodb 是一个开源的no-sql分布式数据库,Mongodb也为我们提供了基于文件的GFS分布式存储系统。因此利用Mongodb我们完全可以实现一个分布式的文件存储以及管理。

下面的内容主要为大家介绍,如何利用java,将大文件存入Mongodb数据库中。我们这里所说的大文件,是指大小在16M以上的文件,这也符合MongodbGFS的说明。

首先我们创建一个java工程,这里我们使用gradle初始化一个java工程,工程结构如下图。

当然这里你也可以使用maven来构建一个java工程,对我们后续工作并不会有影响。

接下来我们去mongodb的官网下载其基于java的驱动包。Mongodbjava驱动程序

这里我们只需要将这一行,复制到我们工程的build.gradle 文件。

然后刷新gradle,我们可以看到jar包已经添加到我们的程序里。

接下来我们编写调用的示例,我们新建一个类叫做MongdbGFS.java。然后获取一个Mongodb的连接,代码如下:

[java] view plain copy

  1. package mongodbGfs;
  2. import com.mongodb.MongoClient;
  3. import com.mongodb.client.MongoDatabase;
  4. /**
  5. *
  6. * @author zhaotong
  7. *
  8. */
  9. public class MongodbGFS {
  10. private MongoClient mongoClient;
  11. //我们进行操作的数据库
  12. private MongoDatabase useDatabase;
  13. //初始化
  14. {
  15. mongoClient=new MongoClient("localhost",27017);
  16. useDatabase=mongoClient.getDatabase("zhaotong");
  17. }
  18. }

接下来,我们先不着急写下面的代码,我们先找到一个文件放到我们工程里面,为了我们之后的测试。我在src下面新建了一个文件夹file,里面存放了一个大约21M的pdf文件。

接下里我们开始进行mongodbGFS文件的存储。

首先我们讲一下mongodbGFS存储的一个原理。这里我们引用mongodb官方文档里的一句话(文档地址):

GridFS is a specification for storing and retrieving files that exceed the BSON document size limit of 16MB. Instead of storing a file in a single document, GridFS divides a file into parts, or chunks, and stores each of those chunks as a separate document.

When you query a GridFS store for a file, the Java driver will reassemble the chunks as needed.

从上面这段话可以简单的了解到,mongodb是将文件进行分块,存储,当查询时,mongodb会帮你把你所需要的块进行组合然后展示给你,因此结合mongodb分布式的特性,我们可以轻易的构建一个分布式的文件存储。

在利用java驱动存储时,当我们获得需要存储的数据库连接之后,我们需要先创建一个bucket,官方的说明如下:

Create a GridFS Bucket

GridFS stores files in two collections: a chunks collection stores the file chunks, and a files collection stores file metadata. The two collections are in a common bucket and the collection names are prefixed with the bucket name.

通过上面的这段话,我们可以知道,mongodb是将文件分为两部分存储,一个是chunks,另一个是files。并且在collection 的名字将会有你bucket的前缀。mongodb支持自定义的bucket的名字,当然也有默认,默认是files。

[java] view plain copy

  1. * @author zhaotong
  2. *
  3. */
  4. public class MongodbGFS {
  5. private MongoClient mongoClient;
  6. //我们进行操作的数据库
  7. private MongoDatabase useDatabase;
  8. //bucket
  9. private GridFSBucket gridFSBucket;
  10. //初始化
  11. {
  12. mongoClient=new MongoClient("localhost",27017);
  13. useDatabase=mongoClient.getDatabase("zhaotong");
  14. // 自定义bucket name
  15. gridFSBucket= GridFSBuckets.create(useDatabase,"zt_files");
  16. // 使用默认的名字
  17. //gridFSBucket=GridFSBuckets.create(useDatabase);
  18. }
  19. }

接下来就是对应的具体操作,代码如下:

[java] view plain copy

  1. package mongodbGfs;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.nio.file.Files;
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. import org.bson.Document;
  12. import org.bson.types.ObjectId;
  13. import com.mongodb.Block;
  14. import com.mongodb.MongoClient;
  15. import com.mongodb.client.MongoDatabase;
  16. import com.mongodb.client.gridfs.GridFSBucket;
  17. import com.mongodb.client.gridfs.GridFSBuckets;
  18. import com.mongodb.client.gridfs.GridFSUploadStream;
  19. import com.mongodb.client.gridfs.model.GridFSFile;
  20. import com.mongodb.client.gridfs.model.GridFSUploadOptions;
  21. /**
  22. *
  23. * @author zhaotong
  24. *
  25. */
  26. public class MongodbGFS {
  27. private MongoClient mongoClient;
  28. // 我们进行操作的数据库
  29. private MongoDatabase useDatabase;
  30. // bucket
  31. private GridFSBucket gridFSBucket;
  32. // 初始化
  33. {
  34. mongoClient = new MongoClient("localhost", 27017);
  35. useDatabase = mongoClient.getDatabase("zhaotong");
  36. // 自定义bucket name
  37. gridFSBucket = GridFSBuckets.create(useDatabase, "zt_files");
  38. // 使用默认的名字
  39. // gridFSBucket=GridFSBuckets.create(useDatabase);
  40. }
  41. // 将文件存储到mongodb,返回存储完成后的ObjectID
  42. public ObjectId saveFile(String url) {
  43. InputStream ins = null;
  44. ObjectId fileid = null;
  45. // 配置一些参数
  46. GridFSUploadOptions options = null;
  47. // 截取文件名
  48. String filename = url.substring((url.lastIndexOf("/") + 1), url.length());
  49. try {
  50. ins = new FileInputStream(new File(url));
  51. options = new GridFSUploadOptions().chunkSizeBytes(358400).metadata(new Document("type", "presentation"));
  52. // 存储文件,第一个参数是文件名称,第二个是输入流,第三个是参数设置
  53. fileid = gridFSBucket.uploadFromStream(filename, ins, options);
  54. } catch (FileNotFoundException e) {
  55. e.printStackTrace();
  56. } finally {
  57. try {
  58. ins.close();
  59. } catch (IOException e) {
  60. }
  61. }
  62. return fileid;
  63. }
  64. // 通过OpenUploadStream存储文件
  65. /**
  66. *
  67. * The GridFSUploadStream buffers data until it reaches the chunkSizeBytes and
  68. * then inserts the chunk into the chunks collection. When the
  69. * GridFSUploadStream is closed, the final chunk is written and the file
  70. * metadata is inserted into the files collection.
  71. *
  72. */
  73. public ObjectId saveFile2(String url) {
  74. ObjectId fileid = null;
  75. GridFSUploadStream gfsupload = null;
  76. // 配置一些参数
  77. GridFSUploadOptions options = null;
  78. // 截取文件名
  79. String filename = url.substring((url.lastIndexOf("/") + 1), url.length());
  80. try {
  81. options = new GridFSUploadOptions().chunkSizeBytes(358400).metadata(new Document("type", "presentation"));
  82. // 存储文件,第一个参数是文件名称,第二个是输入流,第三个是参数设置
  83. gfsupload = gridFSBucket.openUploadStream(filename, options);
  84. byte[] data = Files.readAllBytes(new File(url).toPath());
  85. gfsupload.write(data);
  86. } catch (FileNotFoundException e) {
  87. e.printStackTrace();
  88. } catch (IOException e) {
  89. e.printStackTrace();
  90. } finally {
  91. gfsupload.close();
  92. fileid = gfsupload.getObjectId();
  93. }
  94. return fileid;
  95. }
  96. // 查询所有储存的文件
  97. public List<String> findAllFile() {
  98. List<String> filenames = new ArrayList<>();
  99. gridFSBucket.find().forEach(new Block<GridFSFile>() {
  100. @Override
  101. public void apply(GridFSFile t) {
  102. filenames.add(t.getFilename());
  103. }
  104. });
  105. return filenames;
  106. }
  107. // 删除文件
  108. public void deleteFile(ObjectId id) {
  109. gridFSBucket.delete(id);
  110. }
  111. // 重命名文件
  112. public void rename(ObjectId id, String name) {
  113. gridFSBucket.rename(id, name);
  114. }
  115. // 将数据库中的文件读出到磁盘上,参数,文件路径
  116. public String downFile(String url, ObjectId id) {
  117. FileOutputStream out = null;
  118. String result=null;
  119. try {
  120. out = new FileOutputStream(new File(url));
  121. gridFSBucket.downloadToStream(id, out);
  122. } catch (FileNotFoundException e) {
  123. e.printStackTrace();
  124. }finally {
  125. try {
  126. out.close();
  127. result=out.toString();
  128. } catch (IOException e) {
  129. e.printStackTrace();
  130. }
  131. }
  132. return result;
  133. }
  134. }

对应的单元测试类,大家可以下载运行:

[java] view plain copy

  1. import org.bson.types.ObjectId;
  2. import org.junit.Before;
  3. import org.junit.Ignore;
  4. import org.junit.Test;
  5. import mongodbGfs.MongodbGFS;
  6. public class MongodbGFSTest {
  7. private MongodbGFS mgfs;
  8. @Before
  9. public void init() {
  10. mgfs=new MongodbGFS();
  11. }
  12. // 测试存储
  13. @Ignore
  14. public void saveFile() {
  15. ObjectId id=mgfs.saveFile("src/file/2017 Alitech Archive_1.pdf");
  16. System.out.println(id);
  17. }
  18. //测试存储二
  19. @Ignore
  20. public void saveFile2() {
  21. ObjectId id=mgfs.saveFile2("src/file/2017 Alitech Archive_1.pdf");
  22. System.out.println(id);
  23. }
  24. // 测试查询所有在当前数据库存储的文件
  25. @Ignore
  26. public void findAllFile() {
  27. System.out.println(mgfs.findAllFile());
  28. }
  29. // 测试下载文件,存数据库
  30. @Ignore
  31. public void downFile() {
  32. System.out.println(mgfs.downFile("src/file/alibaba.pdf",new ObjectId("5a6ec218f9afa00c086d94bb")));
  33. }
  34. // 测试删除文件
  35. @Ignore
  36. public void deleteFile() {
  37. mgfs.deleteFile(new ObjectId("5a6ec218f9afa00c086d94bb"));
  38. }
  39. //测试重命名文件
  40. @Test
  41. public void rename() {
  42. mgfs.rename(new ObjectId("5a6ec218f9afa00c086d94bb"), "zhaotong.pdf");
  43. }
  44. }

我们可以在管理工具中看到,我们存储的文件结构如下:

其每个块的存储如下:

如果还有什么问题,可以联系我(1427730623),我将会把工程放到github上,稍后补充一下github地址。

原文链接:点击打开链接

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年02月06日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Create a GridFS Bucket
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档