MogoDB 文件的上傳與下載 GridFS 的使用

GridFS — MongoDB Manual

GridFS 用于存儲(chǔ)和恢復(fù)那些超過16M(BSON文件限制)的文件(如:圖片、音頻、視頻等)。
GridFS 也是文件存儲(chǔ)的一種方式,但是它是存儲(chǔ)在MonoDB的集合中。
GridFS 會(huì)將大文件對(duì)象分割成多個(gè)小的chunk,每個(gè)chunk將作為MongoDB的一個(gè)文檔(document)被存儲(chǔ)在chunks集合中。

GridFS 將文件存儲(chǔ)在兩個(gè)集合中:

  • chunks存儲(chǔ)二進(jìn)制塊。有關(guān)詳細(xì)信息,請(qǐng)參閱塊集合
  • files存儲(chǔ)文件的元數(shù)據(jù)。有關(guān)詳細(xì)信息,請(qǐng)參閱文件集合

GridFS 通過將集合的存儲(chǔ)桶名稱作為前綴,將集合放在公共存儲(chǔ)桶中。默認(rèn)情況下,GridFS 使用兩個(gè)集合,其存儲(chǔ)桶名為 :fs

  • fs.files
{
  "_id" : <ObjectId>,
  "length" : <num>,
  "chunkSize" : <num>,
  "uploadDate" : <timestamp>,
  "md5" : <hash>,
  "filename" : <string>,
  "contentType" : <string>,
  "aliases" : <string array>,
  "metadata" : <any>,
}
  • fs.chunks
{
  "_id" : <ObjectId>,
  "files_id" : <ObjectId>,
  "n" : <num>,
  "data" : <binary>
}

GridFS使用

使用shell命令

MongoDB 提供 mingofiles 工具,可以使用命令行來操作GridFS。四個(gè)主要命令,分別為:
put 存儲(chǔ)命令
get 獲取命令
list 列表命令
delete 刪除命令

# 存儲(chǔ)文件 (執(zhí)行后會(huì)在數(shù)據(jù)庫中就會(huì)多出2個(gè)集合,它們存儲(chǔ)了GridFS文件系統(tǒng)的所有文件信息)
- mongofiles -d 數(shù)據(jù)庫名字 -l "要上傳的文件的完整路徑名" put "上傳后的文件名"

# 獲取文件 (如果不寫-l以及后面的路徑參數(shù),則保存到當(dāng)前位置。)
- mongofiles -d 數(shù)據(jù)庫名字 -l "將文件保存在本地的完整路徑名" get "GridFS文件系統(tǒng)中的文件名"

#列表文件
- mongofiles -d 數(shù)據(jù)庫名字 list

#刪除文件
- mongofiles -d 數(shù)據(jù)庫名字 delete " 文件名 "

使用API

MongoDB支持多種編程語言驅(qū)動(dòng)。比如c、java、C#、NodeJS等。因此可以使用這些語言MongoDB驅(qū)動(dòng)API操作,擴(kuò)展GridFS。

SpringBoot為例:
上次Mongo測試基礎(chǔ)上
官方文檔教程

上傳文件

    //文件操作
    @Autowired
    GridFsTemplate gridFsTemplate;
    @Test
    public void testUpload() throws FileNotFoundException {

        File file = new File("D:\\Test\\demo.zip");
        // 獲取文件名
        String fileName=file.getName().substring(0,file.getName().lastIndexOf("."));
        // 獲取文件后綴
        String contentType = file.getName().substring(file.getName().lastIndexOf(".") + 1, file.getName().length());
        // 獲取文件流
        FileInputStream fileInputStream = new FileInputStream(file);
        // 上傳 return "_id"
        ObjectId objectId = gridFsTemplate.store(fileInputStream, file.getName(),contentType);

        System.out.println(objectId);
    }

自定義桶名稱

config 包下創(chuàng)建 MongoConfig

@Configuration
public class MongoConfig {
    @Bean
    public GridFsTemplate gridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter) {
        return new GridFsTemplate(dbFactory, converter, "pictureFs");
    }
}

再在測試類中上傳文件,就上傳到了pictureFs桶中

上傳文件 -法2

使用GridFSBucket.uploadFromStream 方法
可以使用 GridFSUploadOptions 來配置塊大小或包含其他元數(shù)據(jù)。

    @Test void testUpload2(){
        GridFSBucket bucket=GridFSBuckets.create(mongoTemplate.getDb(),"fs");
        try {
            File file = new File("D:\\Test\\test.zip");
            // 獲取文件名
            String fileName=file.getName().substring(0,file.getName().lastIndexOf("."));
            // 獲取文件后綴
            String contentType = file.getName().substring(file.getName().lastIndexOf(".") + 1);
            // 獲取文件流
            InputStream streamToUploadFrom = new FileInputStream(file);
            // 配置塊大小 或 包含其他元數(shù)據(jù)
            GridFSUploadOptions options = new GridFSUploadOptions()
                    .chunkSizeBytes(358400)
                    .metadata(new Document("type", contentType));

            ObjectId fileId = bucket.uploadFromStream(fileName, streamToUploadFrom, options);

            System.out.println("文件上傳成功-"+fileId);
        } catch (FileNotFoundException e){
            System.out.println("FileNotFoundException:" + e.getMessage());
        }
    }

查詢文件

    //文件查詢
    @Test
    public void testFind(){
        // findAll
        // 可以為 GridFSBuckets.create() 方法指定存儲(chǔ)桶名稱
        GridFSBucket bucket=GridFSBuckets.create(mongoTemplate.getDb(),"bucketName");
        bucket.find().forEach(e-> System.out.println(e.getFilename()));
    }

提供設(shè)置過濾器來限制返回的結(jié)果

bucket.find(Filters.eq("filename","測試文件")).forEach(e-> System.out.println(e.getFilename()));

下載文件

    @Test 
    public void testDownload() throws IOException{
        ObjectId fileId= new ObjectId("626d45071aa7187f36380ee9");
        GridFSBucket bucket=GridFSBuckets.create(mongoTemplate.getDb(),"fs");
        try {
            // 使用輸出流 設(shè)置要保存的路徑
            FileOutputStream streamToDownloadTo = new FileOutputStream("D:\\Test\\downTest.zip");
            // 通過Id下載文件
            bucket.downloadToStream(fileId, streamToDownloadTo);
            // 關(guān)閉輸出流
            streamToDownloadTo.close();

            System.out.println(streamToDownloadTo);
            
        } catch (IOException e) {
            System.out.println("IOException:" + e.getMessage());
        }
    }

重命名文件

    @Test
    public void testRename(){
        ObjectId fileId= new ObjectId("626d45071aa7187f36380ee9");
        GridFSBucket bucket=GridFSBuckets.create(mongoTemplate.getDb(),"fs");
        bucket.rename(fileId,"Test");
    }

刪除文件

    public void deleteRename(){
        ObjectId fileId= new ObjectId("626ba621ac6c406b9208cfb6");
        GridFSBucket bucket=GridFSBuckets.create(mongoTemplate.getDb(),"fs");
        bucket.delete(fileId);
    }

以上,就學(xué)習(xí)了 GridFS在 SpringBoot 中的基本使用方法


擴(kuò)充
multer-gridfs-storage:Mul GridFS存儲(chǔ)引擎,用于Multer將上傳的文件直接存儲(chǔ)到MongoDbGitHub - devconcept/multer-gridfs-storage
gridfs-stream:輕松將文件流式傳輸?shù)組ongoDB GridFS和從MongoDB GridFS流式傳輸文件。GitHub - aheckmann/gridfs-stream

GridFS也有一些問題,
比如它讀取文件的性能并不是很好,因?yàn)槲覀冃枰樵儍纱渭希ㄏ仁莊s.files,再是fs.chunks)才能將文件拼湊出來。
如果我們的文件需要經(jīng)常修改,那么GridFS也不合適,因?yàn)镚ridFS沒法修改單獨(dú)的某個(gè)分塊,要修改文件的話,需要先將該文件刪除,然后重新上傳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容