칠니우 클라우드를 이용한 파일 업로드 및 다운로드 방법

준비 작업

1. 칠니우 클라우드 계정 생성

2. 계정에 로그인하여 개인 센터에서 액세스 키(ak)와 비밀 키(sk) 생성

3. 공개 저장 공간(버킷) 생성

참고: 저장 지역 선택은 사용자의 주요 분포에 따라 결정됩니다.

칠니우 클라우드는 프로젝트를 위해 10GB의 무료 저장 공간을 제공하므로 개발에 적합합니다.

실전 구현

1. Spring Boot 프로젝트에 필요한 의존성 추가

<!--        칠니우 클라우드-->
<dependency>
    <groupId>com.qiniu</groupId>
    <artifactId>qiniu-java-sdk</artifactId>
    <version>[7.13.0, 7.13.99]</version>
</dependency>

<!--        gson, 파일 업로드 시 사용-->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
    <scope>compile</scope>
</dependency>

<!--        @ConfigurationProperties 주석 오류 해결-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

2. yml 파일에 ak, sk 및 버킷 관련 구성 추가

qiniu:
  accessKey: z3214mq2xG5w7-KHQk7oBiJC6sbjrjmlVNai0sai
  secretKey: _wys_Vf2RWpZqG9Hnlq32lQ17wvULnHeJSIjnGez
  bucket: gmgx2024
  prefixUrl: http://siz0shti6.jl-cnm.clouddn.com/

prefixUrl은 여기에 사용됩니다.

3. QiniuConfig 클래스로 구성 받기

@ConfigurationProperties(prefix = "qiniu")
@Data
@Component
public class QiniuConfig {
    private String accessKey;
    private String secretKey;
    private String bucket;
    private String prefixUrl;
}

4. 파일 업로드 핵심 코드 작성

왜 업로드만 설명하나요? 이 버킷은 공개적이므로, 업로드 시 반환된 URL을 데이터베이스에 저장하고, 파일을 다운로드할 때 해당 URL을 사용하기만 하면 됩니다. (나중에 비공개 버킷의 업로드 및 다운로드를 설명합니다)

컨트롤러

@Tag(name="파일 컨트롤러",description = "칠니우 클라우드를 이용한 파일 업로드 및 다운로드")
@RestController
@RequestMapping("file")
public class FileController {
    @Autowired
    private FileService fileService;
    
    @Operation(summary = "uploadFile",description = "칠니우 클라우드를 이용한 파일 업로드")
    @PostMapping("/uploadFile")
    public Result uploadFile(MultipartFile file){
        String url = fileService.upload(file);
        if(url!=null){
            return new Result(Code.UPLOAD_SUCCESS,"파일 업로드 성공",url);
        }
        return new Result(Code.UPLOAD_FAIL,"파일 업로드 실패",null);
    }
    
}

서비스 클래스

package com.example.qiniufileupload.service.impl;
import com.example.qiniufileupload.config.QiniuConfig;
import com.example.qiniufileupload.service.FileService;
import com.google.gson.Gson;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private QiniuConfig qiniuConfig;

    /**
     * 
     * @param file   칠니우 클라우드에 업로드할 파일
     * @return url   업로드된 파일의 전체 URL
     */
    public String upload(MultipartFile file) {

        try {
            // 원본 파일명 가져오기   aaa.jpg
            String originalFilename = file.getOriginalFilename();

            //파일 확장자 extendFileName    jpg
            String extendFileName = originalFilename.substring(originalFilename.lastIndexOf("."));

            // key를 지정하지 않으면 파일 내용의 해시값을 파일명으로 사용하고 날짜 접두사 추가
            LocalDate currentDate = LocalDate.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd/");

            // 새 파일명 구성    2024/8/29/uuid.jpg
            String key = currentDate.format(formatter) + UUID.randomUUID().toString().replace("-", "") + extendFileName;


            // 지정된 Region 객체로 구성 클래스 생성
            Configuration zone = new Configuration(Zone.huanan());//처음 선택한 지역은 남부 중국


            // MultipartFile에서 직접 입력 스트림 가져오기, 로컬에 먼저 저장하지 않고 업로드
            InputStream inputStream = file.getInputStream();

            //Auth 객체 생성, ak와 sk 입력
            Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
            //업로드 토큰 획득
            String upToken = auth.uploadToken(qiniuConfig.getBucket());
            System.out.println(upToken);
            //z3214mq2xG5w7-KHQk7oBiJC6zojrjmlVNcn0sai:oHRCCHPiB2YlJxxCYtDyVOb3lCs=:eyJzY29wZSI6ImdtZ3gyMDI0IiwiZGVhZGxpbmUiOjE3MjQ5Mjc2NjN9


            // null 조건 검증 생략
            try (InputStream ignored = inputStream)
            {
                UploadManager uploadManager = new UploadManager(zone);//zone 지정

                //이미지 칠니우 클라우드에 업로드
                Response response = uploadManager.put(inputStream, key, upToken,null,null);

                /**
                 * gson을 사용하여 브라우저 응답 body 문자열을 DefaultPutRet의 인스턴스로 파싱
                 *                                     ↓
                 *          public final class DefaultPutRet {
                 *              public String hash;
                 *              public String key;//칠니우 클라우드 저장 공간에서의 이름
                 *
                 *              public DefaultPutRet() {
                 *              }
                 *          }
                 *
                 */

                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);

                String url = "";
                url = qiniuConfig.getPrefixUrl() + putRet.key;

                return url;
            } catch (IOException ex) {

                return null;
            }
        } catch (Exception e) {

            return null;
        }

    }
    
}

5. Knife4j로 테스트

먼저 이미지 파일을 준비합니다.

Knife4j 인터페이스에서 해당 파일을 선택하여 업로드합니다.

반환된 URL 주소를 가져옵니다.

칠니우 클라우드에 저장된 폴더에서 방금 업로드한 이미지를 확인합니다.

사용 시나리오

파일 업로드가 필요한 비즈니스를 구현할 때, 업로드 성공 후 파일 URL을 데이터베이스에 저장하고, 필요할 때 데이터베이스에서 해당 파일 URL을 조회하여 프론트엔드에서 해당 파일을 렌더링할 수 있습니다.


비공개 버킷의 업로드 및 다운로드

1. 비공개 버킷 생성

2. 관련 구성 수정

3. 업로드 및 다운로드 핵심 코드 작성

컨트롤러

@Tag(name="파일 컨트롤러",description = "칠니우 클라우드를 이용한 파일 업로드 및 다운로드")
@RestController
@RequestMapping("file")
public class FileController {
    @Autowired
    private FileService fileService;

    @Operation(summary = "uploadFile",description = "칠니우 클라우드를 이용한 파일 업로드")
    @PostMapping("/uploadFile")
    public Result uploadFile(MultipartFile file){
        String url = fileService.upload(file);
        if(url!=null){
            return new Result(Code.UPLOAD_SUCCESS,"파일 업로드 성공",url);
        }
        return new Result(Code.UPLOAD_FAIL,"파일 업로드 실패",null);
    }
    
    @Operation(summary = "downloadFile",description = "칠니우 클라우드를 이용한 파일 다운로드")
    @PostMapping("/downloadFile/{fileName}")
    public Result downloadFile(@PathVariable String fileName){
        String url = fileService.download(fileName);
        if(url!=null){
            return new Result(Code.DOWNLOAD_SUCCESS,"파일 다운로드 성공",url);
        }
        return new Result(Code.DOWNLOAD_FAIL,"파일 다운로드 실패",null);
    }

}

서비스 클래스

@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private QiniuConfig qiniuConfig;

    /**
     *
     * @param file   칠니우 클라우드에 업로드할 파일
     * @return url   업로드된 파일의 전체 URL
     */
    public String upload(MultipartFile file) {

        try {
            // 원본 파일명 가져오기   aaa.jpg
            String originalFilename = file.getOriginalFilename();

            //파일 확장자 extendFileName    jpg
            String extendFileName = originalFilename.substring(originalFilename.lastIndexOf("."));

            String key =  UUID.randomUUID().toString().replace("-", "") + extendFileName;


            // 지정된 Region 객체로 구성 클래스 생성
            Configuration zone = new Configuration(Zone.huanan());//처음 선택한 지역은 남부 중국

            // MultipartFile에서 직접 입력 스트림 가져오기, 로컬에 먼저 저장하지 않고 업로드
            InputStream inputStream = file.getInputStream();

            //Auth 객체 생성, ak와 sk 입력
            Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
            //업로드 토큰 획득
            String upToken = auth.uploadToken(qiniuConfig.getBucket());
            System.out.println(upToken);
            //z3214mq2xG5w7-KHQk7oBiJC6zojrjmlVNcn0sai:oHRCCHPiB2YlJxxCYtDyVOb3lCs=:eyJzY29wZSI6ImdtZ3gyMDI0IiwiZGVhZGxpbmUiOjE3MjQ5Mjc2NjN9


            // null 조건 검증 생략
            try (InputStream ignored = inputStream)
            {
                UploadManager uploadManager = new UploadManager(zone);//zone 지정

                //이미지 칠니우 클라우드에 업로드
                Response response = uploadManager.put(inputStream, key, upToken,null,null);

                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);

                String url = "";
                url = qiniuConfig.getPrefixUrl() + putRet.key;

                return url;
            } catch (IOException ex) {
                return null;
            }
        } catch (Exception e) {
            return null;
        }

    }


    @Override
    public String download(String fileName) {
        String urlString = "";
        try {
            // domain   다운로드 domain, 예: qiniu.com【필수】
            // useHttps https 사용 여부【필수】
            // key      칠니우 클라우드 저장소에 있는 리소스의 key【필수】
            String domain = qiniuConfig.getPrefixUrl();
            //todo domain 수정 필요
            DownloadUrl url = new DownloadUrl(domain, qiniuConfig.getUseHttps(), fileName);

            // 유효 기간 설정
            long expireInSeconds = 60;
            long deadline = System.currentTimeMillis() / 1000 + expireInSeconds;
            Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
            urlString = url.buildURL(auth, deadline);
            System.out.println(urlString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return urlString;
    }

}

4. 테스트

여기서 URL 형식에 주의하십시오. 유효 기간과 토큰이 포함되어 있습니다.

태그: 칠니우 스프링부트 클라우드저장소 파일업로드 파일다운로드

6월 10일 17:03에 게시됨