본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


몽고DB/Java 몽고DB

Java 몽고DB 파일 업로드 (Java mongodb file, Java mongodb fs)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 7. 3.

Java에서 몽고DB에 파일을 등록하는 방법 입니다.

몽고DB에서는 다른 데이터베이스와 마찬가지로 파일을 업로드 할 수 있게 해 주고 있습니다.

파일형태는 바이너리로 변환하여 컬렉션에 저장이 되며, 다른 정보도 포함하여 저장 할 수 있습니다.

대용량 파일 저장은 아쉽게도 지원하지 않으며 16메가바이트 이하의 파일을 업로드 할 것을 권장하고 있습니다.

 

파일 업로드 하는 방법입니다.

GridFSBucket클래스와 GridFSUploadOptions클래스를 사용 하였습니다.

private void insertFile() throws Exception{
    Document doc = new Document("type","image");
    doc.append("content_type", "image/png");
    doc.append("my_id", "abcd_1234_5678");
    doc.append("desc", "한글 입력입니다.");
    doc.append("date", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) );

    InputStream inStream = new FileInputStream(new File("E:/test.png"));
    GridFSBucket gridBucket = GridFSBuckets.create(template.getDb());   //mongoClient.getDatabase("이름")

    GridFSUploadOptions uploadOptions = new GridFSUploadOptions().chunkSizeBytes(1024).metadata(doc);
    ObjectId fileId = null;
    fileId = gridBucket.uploadFromStream("re_name.png", inStream, uploadOptions);  //바꿀파일명을 넣어주세요.
    System.out.println("fileId : " + fileId);
    inStream.close();
}

 

코드 내용은 매우 직관적이라 어렵지 않습니다.

template 객체는 MongoTemplate 클래스 입니다.

만약 몽고클라이언트를 사용한다면 주석친 부분의 내용으로 변경하여 create 메소드에 파라미터로 넣어주면 됩니다.

파일에서 InputStream을 겨저 온 뒤에 uploadFromStream 이라는 메소드를 통해서 등록하여 주었습니다.

Document 클래스는 metadata 라는 속성에 저장이 되며 key, value 형식의 데이터를 넣어주게됩니다.

요렇게 잘 동작 했습니다. 저장하고 나면 고유 id값을 리턴하여 줍니다.

 

이렇게 데이터를 등록하면 컬렉션이 2개가 생성(없다면) 됩니다.

fs.chunks라는 컬렉션과 fs.files라는 컬렉션 입니다.

fs.chunks에는 파일에 관한 바이너리 데이터를 모아두는 곳 이며, fs.files 컬렉션은 사용자가 직접 조회할 수 있는 정보를 담은 컬렉션 입니다.

실제 컬렉션에서도 어렵지 않게 내용을 확인 할 수 있습니다.

metadata라는 필드값이 Document 클래스로 넣어준 값 입니다.

 

사실 fs.chunks 컬렉션을 직접적으로 관리할 일은 없습니다. 대부분 fs.files 컬렉션을 관리 합니다.

그러면 이제 조회하는 기능을 한번 확인하여 보겠습니다.

private void getFile() throws Exception{
    GridFSBucket gridBucket = GridFSBuckets.create(template.getDb());

    Document query = new Document();
    query.append("metadata.my_id", new Document("$eq", "abcd_1234_5678"));
    query.append("metadata.date", new Document("$gte", "2020-07-01 00:00:00"));
    query.append("metadata.date", new Document("$lte", "2020-07-05 23:59:59"));

    GridFSFindIterable itor = gridBucket.find(query);

    int i = 0;
    for (GridFSFile file : itor) { 
        System.out.println(file.getFilename() + " : " + file.getMetadata());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        gridBucket.downloadToStream(file.getId(), baos);
        OutputStream outputStream = new FileOutputStream("E:/DDOWN/down"+i+".png");  //받을 디렉토리+파일명
        baos.writeTo(outputStream);
        try {
            baos.close();
        } catch (Exception e) {

        }
        try {
            outputStream.close();
        } catch (Exception e) {

        }
        i++;
    }
}

 

마찬가지로 어렵지 않는 코드 입니다.

재미있는 점은 질의를 위한 부분입니다. 통상적으로 사용했던 Query 클래스를 사용하지 않고 Document 클래스를 사용하였습니다.

입력한 데이터인 metadata에 접근하여 조회를 하는 모습입니다.

조회를 하고 난 뒤에는 각종 등록 정보를 가져왔으며, downloadToStream 메소드를 통해서 파일을 Byte스트림에 담아두었습니다.

GridFSBucket 클래스에서 fs.find를 통해서 나온 데이터는 n개이므로 반복문을 활용하여 정보를 가져오도록 합니다.

딱히 어려운것은 없어 보입니다.

 

다음으로 파일을 삭제하는 부분 입니다.

private void deleteFile() throws Exception{
    GridFSBucket gridBucket = GridFSBuckets.create(template.getDb());
    Bson filter = Filters.regex("metadata.web_id", "abcd_1234_5678");
    GridFSFindIterable itor = gridBucket.find(filter);
    for (GridFSFile file : itor) {
        System.out.println(file.getFilename());
        System.out.println(file.getMetadata());
        gridBucket.delete(file.getId());
    }		
}

 

delete라는 메소드를 호출하였습니다.

위 예제처럼 Bson이라는 클래스를 활용하면 아주 간단한 질의를 할 수 있습니다.

삭제를 하게되면 fs.chunks와 fs.files 컬렉션 둘 다 내용이 제거됩니다.

 

fs.files 컬렉션은 다른 컬렉션과 마찬가지로 인덱스를 지원합니다.

물론 fs.chunks 컬렉션도 지원합니다만 일반적으로 조회를 하지는 않습니다.

조회할 대상에 인덱스를 부여 할 수 있습니다.

 

그 외에도 rename이라는 메소드를 통해 파일 이름을 이름을 바꿀 수 있으며 fs.files 컬렉션 drop으로 전부 제거를 할 수 있습니다.

아쉽게도 update에 대한 내용은 GridFSBucket 컬렉션에서 확인하지를 못하였습니다. (제가 못 찾았겠지요..ㅠ)

metadata(메타정보)를 바꾸려면 몽고DB에서 일반 업데이트를 사용하듯이 해 주어야 합니다.

아래는 일반 Update 기능을 통해서 컬렉션의 meta정보를 바꾸어준 모습 입니다.

요렇게 기존 한글로 되어있던 meatdata의 doc값이 영문 "no"로 바뀌어 콘솔에 출력되었습니다.

 

이제 사용한 소스코드 전체를 살펴보겠습니다.

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.MongoTemplate;

import com.mongodb.ConnectionString;
import com.mongodb.client.MongoClients;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.gridfs.model.GridFSUploadOptions;
import com.mongodb.client.model.Filters;
import com.mongodb.client.MongoClient;
import com.mongodb.MongoClientSettings;

public class TestMainClass {
    
    public MongoClient mongoClient = null;
    public MongoTemplate template = null;    
    
    
    public static void main(String args[]){

    }
    
    //등록
    private void insertFile() throws Exception{
        Document doc = new Document("type","image");
        doc.append("content_type", "image/png");
        doc.append("my_id", "abcd_1234_5678");
        doc.append("desc", "한글 입력입니다.");
        doc.append("date", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) );
        
        InputStream inStream = new FileInputStream(new File("가저올경로/파일이름.png"));
        GridFSBucket gridBucket = GridFSBuckets.create(template.getDb());   //mongoClient.getDatabase("이름")

        GridFSUploadOptions uploadOptions = new GridFSUploadOptions().chunkSizeBytes(1024).metadata(doc);
        ObjectId fileId = null;
        fileId = gridBucket.uploadFromStream("바꿀이름.png", inStream, uploadOptions);
        System.out.println("fileId : " + fileId);
        inStream.close();
    }

    //가져오기
    private void getFile() throws Exception{
        GridFSBucket gridBucket = GridFSBuckets.create(template.getDb());
        
        Document query = new Document();
        query.append("metadata.my_id", new Document("$eq", "abcd_1234_5678"));
        query.append("metadata.date", new Document("$gte", "2020-07-01 00:00:00"));
        query.append("metadata.date", new Document("$lte", "2020-07-05 23:59:59"));
        
        GridFSFindIterable itor = gridBucket.find(query);
        
        for (GridFSFile file : itor) {
            System.out.println(file.getFilename() + " : " + file.getMetadata());
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            gridBucket.downloadToStream(file.getId(), baos);
            OutputStream outputStream = new FileOutputStream("다운로드 경로/다운받을 파일명");
            baos.writeTo(outputStream);
            try {
                baos.close();
            } catch (Exception e) {

            }
            try {
                outputStream.close();
            } catch (Exception e) {

            }
        }
    }
    
    //삭제
    private void deleteFile() throws Exception{
        GridFSBucket gridBucket = GridFSBuckets.create(template.getDb());
        Bson filter = Filters.regex("metadata.web_id", "abcd_1234_5678");
        GridFSFindIterable itor = gridBucket.find(filter);
        for (GridFSFile file : itor) {
            System.out.println(file.getFilename());
            System.out.println(file.getMetadata());
            gridBucket.delete(file.getId());
        }        
    }
    
    //접속
    public void init() {
        try {
            final String combineUrl = "mongodb://주소/testerdb";
            ConnectionString connString = new ConnectionString(combineUrl);            
            MongoClientSettings settings = MongoClientSettings.builder()
                    .applyConnectionString(connString)
                    .retryWrites(true)
                    .build();
            mongoClient = MongoClients.create(settings);
            template = new MongoTemplate(mongoClient, "testerdb");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    //종료
    public void close(){
        try {
            template = null;
            mongoClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
        
}

 

위 내용에 사용된 몽고db 버전입니다.

* maven 기준입니다.

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.11.1</version>
</dependency>

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>2.1.17.RELEASE</version>
</dependency>

 

이상으로 몽고db에서 파일을 저장 및 가져오기, 삭제하기 방법에 대해서 살펴 보았습니다.

궁굼하거나 틀린부분은 언제든 연락주세요!

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글