프로그래밍 일기/Java & Spring

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

MakeMe 2023. 7. 12. 09:52
반응형
파일 다운로드 로직
 

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

파일 업로드 로직 [Spring Boot] 단일, 다중 파일 업로드 로직 구현 feat.Nuxt3 버전 정보 자바 11 Spring Boot 2.7.13 Nuxt 3.6.2 마이바티스 2.3.1 FileUtil.java Controller나 Service에 직접 작성해도 무관하나 따로 Util

taeme.tistory.com

 

버전 정보

자바 11

Spring Boot 2.7.13

Nuxt 3.6.2

마이바티스 2.3.1

 

FileUtil.java

Controller나 Service에 직접 작성해도 무관하나 따로 Util파일을 만들어 관리하는 것이 좋습니다.

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 Map fileUploadUtil(MultipartFile file, String uploadPath) throws Exception {
        Map result = new HashMap();

        if (file.getSize() != 0) {
            String currentTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
            String originalFileName = file.getOriginalFilename(); // 파일 기존 이름
            String ext = extractExt(originalFileName); // 파일 확장자
            String saveFileName = currentTime + "." + ext; // DB에 저장할 파일 이름

            String uploadFilePath = serverFilePath + uploadPath + "/" + saveFileName;

            File uploadFile = new File(uploadFilePath);

            // 해당 경로에 폴더가 없으면 폴더를 생성한다.
            if (!uploadFile.exists()) {
                uploadFile.mkdirs();
            }

            Path path = Paths.get(uploadFilePath).toAbsolutePath();

            file.transferTo(path.toFile());

            Map map = new HashMap();

            map.put("filePath", uploadPath + "/" + saveFileName);
            map.put("saveFileName", saveFileName);
            map.put("originalFileName", originalFileName);
            map.put("fileExt", ext);
            map.put("fileSize", file.getSize());

            result = map;
        }

        return result;
    }

    public String extractExt(String fileName) {
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }
}

 

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

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

 

CommonController.java
package com.example.testapi.api.common;

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;

@RestController
public class CommonController {
    private final CommonService commonService;

    public CommonController(CommonService commonService) {
        this.commonService = commonService;
    }

    @PostMapping("/file/add")
    public Map addFile(@RequestParam Map params, MultipartFile[] fileArray) throws Exception {
        return commonService.addFile(params, fileArray);
    }

}

 

CommonService.java
package com.example.testapi.api.common;

import com.example.testapi.config.util.FileUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CommonService {
    private final CommonMapper commonMapper;

    private final FileUtil fileUtil;

    public CommonService(CommonMapper commonMapper, FileUtil fileUtil) {
        this.commonMapper = commonMapper;
        this.fileUtil = fileUtil;
    }

    public Map addFile(Map params, MultipartFile[] fileArray) throws Exception {
        Map result = new HashMap();

        int fileGroupId = commonMapper.loadFileGroupId();
        if (fileArray.length > 0) {
            for (int i = 0; i < fileArray.length; i++) {
                MultipartFile file = fileArray[i];
                Map fileInfo = fileUtil.fileUploadUtil(file, "testFolder");
                fileInfo.put("fileGroupId", fileGroupId);
                commonMapper.addFile(fileInfo);
            }
        }
        result.put("code", 200);
        result.put("data", new HashMap<>());
        result.put("message", "success");

        return result;
    }

}

FileUtil을 통해 파일을 업로드한 후 DB에 파일에 대한 정보를 Insert

 

CommonMapper.java
package com.example.testapi.api.common;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;
import java.util.Map;

@Mapper
public interface CommonMapper {

    int loadFileGroupId() throws Exception;

    int addFile(Map params) throws Exception;

}

 

CommonMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.testapi.api.common.CommonMapper">

    <select id="loadFileGroupId" resultType="Integer">
        /* loadFileGroupId */
        SELECT IFNULL(MAX(FILE_GROUP_ID + 1), 1) FROM FILE_MASTER
    </select>

    <insert id="addFile">
        <selectKey keyProperty="fileId" resultType="Integer" order="BEFORE">
            SELECT IFNULL(MAX(FILE_ID + 1), 1) FROM FILE_MASTER
        </selectKey>
        /* addFile */
        INSERT INTO FILE_MASTER (
            FILE_ID
            , FILE_GROUP_ID
            , SAVE_FILE_NAME
            , ORIGINAL_FILE_NAME
            , FILE_PATH
        ) VALUES (
            #{fileId}
            , #{fileGroupId}
            , #{saveFileName}
            , #{originalFileName}
            , #{filePath}
        )

    </insert>
</mapper>

 

vue 파일 함수 내용
<script setup>
import {ref} from 'vue';

const singleFile = ref('');
const multipleFile = ref([]);
const singleFileDescription = ref('');
const multipleFileDescription = ref('');

const singleFileChange = (e) => {
  singleFile.value = e.target.files[0];
}

const multipleFileChange = (e) => {
  multipleFile.value = e.target.files;
}

const addFile = async (type) => {
  const formData = new FormData();
  if (type === 'single') {
    formData.append('fileArray', singleFile.value); // 파일 객체
    formData.append('description', singleFileDescription.value); // 파일 설명 input
  } else {
    for (var i = 0; i < multipleFile.value.length; i++) {
      formData.append('fileArray', multipleFile.value[i]); // 파일 객체
    }
    formData.append('description', multipleFileDescription.value); // 파일 설명 input
  }

  await useFetch('http://localhost:8080/file/add', {
    method: 'POST',
    body: formData,
  });
}
</script>
반응형