프로그래밍 일기/Java & Spring

[Spring Boot] 파일 다운로드 로직 구현 feat.Nuxt3

MakeMe 2023. 7. 12. 14:48
반응형
파일 업로드 로직
 

[Spring Boot] 단일, 다중 파일 업로드 로직 구현 feat.Nuxt3

버전 정보 자바 11 Spring Boot 2.7.13 Nuxt 3.6.2 마이바티스 2.3.1 FileUtil.java Controller나 Service에 직접 작성해도 무관하나 따로 Util파일을 만들어 관리하는 것이 좋습니다. CommonController.java package com.example.t

taeme.tistory.com

 

버전 정보

자바 11

Spring Boot 2.7.13

 

들어가기에 앞서

해당 로직을 무조건 FileUtil을 만들어서 진행할 필요는 없습니다. 필요에 따라 Controller에 FileUtils 로직을 작성하여 구현하셔도 됩니다. 하지만 저는 프로세스 과정을 다른 로직들과 동일하게 하고 싶어 Controller와 Service를 구현하여 작성했습니다.

 

CommonController.java
@GetMapping("/file/download")
public ResponseEntity<Object> downloadFile(@RequestParam Map params) throws Exception {
    return commonService.downloadFile(params);
}

 

CommonService.java
public ResponseEntity<Object> downloadFile(Map params) throws Exception {
    return fileUtil.fileDownload(commonMapper.loadFile(params).get(0));
}

 

CommonMapper.java
List<Map> loadFile(Map params) throws Exception;

 

CommonMapper.xml
<select id="loadFile" resultType="Map">
    /* loadFile */
    SELECT *
    FROM FILE_MASTER
    <if test='fileId != "" and fileId != null'>
    WHERE FILE_ID = #{fileId}
    </if>
    ORDER BY FILE_ID DESC
</select>

 

FileUtil

package com.example.testapi.config.util;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class FileUtil {

    @Value("${server.file.path}")
    private String serverFilePath;

    //파일 다운로드
    public ResponseEntity<Object> fileDownload (Map params) throws Exception {
        String folderPath = params.get("FILE_PATH").toString();
        String originalFileName = params.get("ORIGINAL_FILE_NAME").toString();
        String path = serverFilePath + folderPath;

        try {
            Path filePath = Paths.get(path);
            Resource resource = new InputStreamResource(Files.newInputStream(filePath)); // 파일 resource 얻기

            HttpHeaders headers = new HttpHeaders();
            headers.setContentDisposition(ContentDisposition.builder("attachment").filename(originalFileName).build());  // 다운로드 되거나 로컬에 저장되는 용도로 쓰이는지를 알려주는 헤더

            return new ResponseEntity<Object>(resource, headers, HttpStatus.OK);
        } catch(Exception e) {
            return new ResponseEntity<Object>(null, HttpStatus.CONFLICT);
        }
    }
}

String folderPath, path 같은 경우 저는 DB에서 정보를 조회한 후 가져오기 때문에 위와 같이 설정되어 있고 만약 하드코딩으로 넣고싶다면 그렇게 하셔도 무관합니다. ex) C:/user/Desktop 등

 

application.properties
# 파일 업로드 서버 경로
server.file.path=D:/Users/wbsoft/Desktop/

위 fileUtils에서 직접 입력한다면 없어도 무관합니다.

 

vue 파일
location.href='http://localhost:8080/file/download?fileId=' + fileId;

$fetch나 useFetch를 통해 get통신을 할 경우에는 특정 라이브러리가 필요하다고 알고 있습니다. 해당 두 함수는 vue에서 값을 받아오고 location은 브라우저에서 file 값을 받아오기 때문에 차이가 있는 것 같습니다.

반응형