본문 바로가기
프로그래밍/Springboot-토이프로젝트

Springboot로 파일업로드와 파일다운로드 구현하기

by 코이킹 2021. 9. 28.
반응형

이번 포스트에서는 Springboot로 만든 API로 파일 업로드와 다운로드를 구현하기 위한 설정과 방법에 대해 정리했습니다. 


1. 【API】 설정방법 

파일 업로드는 Multipart-form을 사용해서 API에 요청을 보내는 것으로 구현할 수 있습니다.  
Springboot에서는 기본적으로 파일 업로드를 위한 설정이 이미 완료되어있으므로 추가로 설정할 필요는 없이 그냥 코딩을 해도 괜찮습니다. 

 

DispatcherServlet을 보면 설정이 되어 있음을 알 수 있음.

 


저는 업로드할 파일의 용량과 요청시의 용량 제한만 변경했습니다. 
변경하기 위한 방법은 아래와 같이 프로퍼티 파일에 파라미터 값을 설정해주면 됩니다. 


2. 코드

- 파일 데이터를 처리하는 서비스 

@Service
public class FileStorageService {

	@Value("${property.app.upload-path}")
	private String uploadPath;

	public List<String> save(MultipartFile[] files, int itemId) {
		try {
			List<String> uploadedFiles = new ArrayList<String>();
			System.out.println("Resource Path : ["+uploadPath+"]");
			
			String uploadDirPath = uploadPath+itemId+"\\";
			File uploadDir = new File(uploadDirPath);
			Path root = Paths.get(uploadDirPath);
			if (!uploadDir.exists()) {
				Files.createDirectory(root);
			}
			
			int cnt = 0;
			for (MultipartFile file : files) {
				String fileName = 
						new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
					    + "_"+
					    file.getOriginalFilename();
				
				System.out.println("[ "+cnt+" ]"+ fileName);
				
				Files.copy(file.getInputStream(), root.resolve(fileName));
				uploadedFiles.add(fileName);
				
				cnt++;
			}

			return uploadedFiles;
			
		} catch (Exception e) {
			throw new RuntimeException("Could not store the file. Error: " + e.getMessage());
		}
	}
	
	public String saveOne(MultipartFile file, int itemId) {
		try {
			System.out.println("Resource Path : [" + uploadPath + "]");
			
			String uploadDirPath = uploadPath+itemId+"\\";
			File uploadDir = new File(uploadDirPath);
			Path root = Paths.get(uploadDirPath);
			if (!uploadDir.exists()) {
				Files.createDirectory(root);
			}
			
			String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_"
					+ file.getOriginalFilename();

			Files.copy(file.getInputStream(), root.resolve(fileName));

			
			return fileName;

		} catch (Exception e) {
			throw new RuntimeException("Could not store the file. Error: " + e.getMessage());
		}
	}

	
	public Resource load(String filename, int itemId) {
		
		String filePath = uploadPath+itemId+"\\"+filename;
		try {
			Path file = Paths.get(filePath);
			Resource resource = new UrlResource(file.toUri());

			if (resource.exists() || resource.isReadable()) {
				return resource;
			} else {
				throw new RuntimeException("Could not read the file!");
			}
		} catch (MalformedURLException e) {
			throw new RuntimeException("Error: " + e.getMessage());
		}
	}

	
	public void deleteFile(String filename) {
		Path file = Paths.get(filename);
		FileSystemUtils.deleteRecursively(file.toFile());
	}

}

- 컨트롤러 

	@PostMapping("items/{itemId}/upload-file")
	public ResponseEntity<String> uploadFileOne(
			@RequestParam(value = "file") MultipartFile file,
			@PathVariable("itemId") int itemId
			) {
		log.info("ItemAdminController uploadFileOne ID : " + itemId + "fileName : "+file.getOriginalFilename());
		String fileName = null;
		try {
			fileName = fileStorageService.saveOne(file, itemId);
			return ResponseEntity.status(HttpStatus.OK).body(fileName);
			
		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(fileName);
		}
	}
	
	
	@PostMapping("items/{itemId}/upload-files")
	public ResponseEntity<List<String>> uploadFiles(
			@RequestParam(value = "files") MultipartFile[] files,
			@PathVariable("itemId") int itemId
			) {
		log.info("ItemAdminController uploadFiles ID : " + itemId);
		for (MultipartFile file : files) {
			System.out.println("File Name : "+file.getOriginalFilename());
		}
		List<String> fileNames = null;
		try {
			fileNames = fileStorageService.save(files, itemId);
			return ResponseEntity.status(HttpStatus.OK).body(fileNames);
			
		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(fileNames);
		}
	}

	
	@GetMapping("items/{itemId}/{filename:.+}")
	public ResponseEntity<Resource> getFile(
			@PathVariable int itemId,
			@PathVariable String filename ) {
		log.info("ItemAdminController getFile filename : "+filename);
		Resource file = fileStorageService.load(filename, itemId);
		return ResponseEntity.ok()
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file);
	}

파일 하나를 업로드시에는 @RequestParam으로 MultipartFile을 받으면 되며,

동시에 파일을 여러 개 업로드 시에는 @RequestParam으로 MultipartFile의 배열을 받으면 됩니다.

 

 

3.【Client】 Postman에서 요청하기 

  ※ Postman으로 HTTP Request시 설정 

    1) Request Method는 POST방식을 선택합니다.

    2) Request Body의 데이터는 form-data를 선택합니다.

    3) Request Parameter는 Key값 Spring boot 컨트롤러의 MultipartFile 변수명과 일치시켜주어야 합니다. 

 

 

- 파일 하나를 업로드하기 

 

- 파일 여러개를 업로드하기 

- 업로드한 결과

 

- 파일 다운로드 

 

4. 전체 소스코드 

https://github.com/leeyoungseung/item-admin

 

반응형

댓글