Search

파일 업로드 / 다운로드

유형
파일처리
공부
공부
Date
2023/03/14 → 2023/03/16
링크
비고
파일 업로드 / 다운로드의 개념을 익히기 위한 예제입니다. (프로젝트 실적용 X)
파일 업로드 / 다운로드 의 구조
구현과정
application.properties 에 DB 에 대한 정보가 있다는 가정하에 진행합니다.

dependency 추가 / WebMvcConfig 설정

(1) dependency 추가
<!-- Multipart File --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.0</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
HTML
복사
(2) WebMvcConfig 설정
내부 경로를 이용하는게 아니라 외부 경로를 사용하기 때문에 필요한 설정이다.
package multi.second.project.domain.File; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { // url: localhost8080:/list/** 에 접속했을 때에 파일에 접근 // 나중에 화면단의 <img src=...> 에서 src 에 들어간다. private String connectPath = "/list/**"; // 실제 이미지가 저장되어 있는 외부경로 (file:/// = C:/ 라고 생각하자) // 끝에 꼭 '/' 로 닫아줘야 한다. private String resourcePath = "file:///upload/"; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(connectPath) .addResourceLocations(resourcePath); } }
Java
복사

Entity 생성

package multi.second.project.domain.File; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Data @Entity @NoArgsConstructor public class Files { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) int fno; String filename; String fileOriName; String fileurl; @Builder public Files(int fno, String filename, String fileOriName, String fileurl) { this.fno = fno; this.filename = filename; this.fileOriName = fileOriName; this.fileurl = fileurl; } }
Java
복사

DTO 생성

package multi.second.project.domain.File; import lombok.*; @Setter @Getter @ToString @NoArgsConstructor public class FilesDto { private int fno; private String filename; private String fileOriName; private String fileurl; public Files toEntity(){ Files build = Files.builder() .fno(fno) .filename(filename) .fileOriName(fileOriName) .fileurl(fileurl) .build(); return build; } @Builder public FilesDto(int fno, String filename, String fileOriName, String fileurl) { this.fno = fno; this.filename = filename; this.fileOriName = fileOriName; this.fileurl = fileurl; } }
Java
복사

Repository 생성

package multi.second.project.domain.File; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface FilesRepository extends JpaRepository<Files, Integer> { }
Java
복사

Service 생성

package multi.second.project.domain.File; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @Service public class FilesService { @Autowired FilesRepository filesRepository; // 파일 저장 public void save(Files files) { Files f = new Files(); f.setFilename(files.getFilename()); f.setFileOriName(files.getFileOriName()); f.setFileurl(files.getFileurl()); filesRepository.save(f); } // 파일 다운로드 @Transactional public List<FilesDto> getFilesList(){ List<Files> files = filesRepository.findAll(); List<FilesDto> fileDtoList = new ArrayList<>(); for(Files file : files){ FilesDto dto = FilesDto.builder() .fno(file.getFno()) .filename(file.getFilename()) .fileOriName(file.getFileOriName()) .fileurl(file.getFileurl()) .build(); fileDtoList.add(dto); } return fileDtoList; } }
Java
복사

Controller 생성

package multi.second.project.domain.File; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.util.List; @Controller public class FilesController { @Autowired FilesService filesService; // 파일 업로드 화면 @RequestMapping("/insert") public String Insert() { return "insert.html"; } // 파일 업로드 처리 @RequestMapping("/fileinsert") public String fileinsert(HttpServletRequest request, @RequestPart MultipartFile files) throws Exception { Files file = new Files(); String sourceFileName = files.getOriginalFilename(); String sourceFileNameExtension = FilenameUtils.getExtension(sourceFileName).toLowerCase(); File destinationFile; String destinationFileName; // 실제 resource 가 저장되는 외부 경로 String fileUrl = "C:/upload/"; do { destinationFileName = RandomStringUtils.randomAlphanumeric(32) + "." + sourceFileNameExtension; destinationFile = new File(fileUrl + destinationFileName); } while (destinationFile.exists()); destinationFile.getParentFile().mkdirs(); files.transferTo(destinationFile); file.setFilename(destinationFileName); file.setFileOriName(sourceFileName); file.setFileurl(fileUrl); filesService.save(file); return "redirect:/insert"; } // 전체 파일 리스트 @GetMapping("/list") public String list(Model model){ List<FilesDto> filesDtoList = filesService.getFilesList(); model.addAttribute("filesList", filesDtoList); return "list"; } }
Java
복사
resource 를 저장하는 경로는 외부경로여야 합니다.
(내부경로(프로젝트 내부)일 경우 배포시 이미지가 엑박으로 뜹니다.)

View 생성

(1) 업로드 화면
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <title>Main</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" href="/css/main_layout.css"/> </head> <body> <form action="/fileinsert" method="post" enctype="multipart/form-data"> <input type="file" name="files"> <button type="submit">보내기</button> </form> </body> </html>
HTML
복사
(2) 다운로드 화면
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <title>Main</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" href="/css/main_layout.css"/> </head> <body> <!-- 반복문을 이용하여 전체 이미지 출력 --> <!-- 이를 활용하여 단건 처리도 가능하다 --> <div th:each="files : ${filesList}"> <img th:src="@{/list/} + ${files.filename}"> </div> </body> </html>
HTML
복사
결과
DB
화면출력
위 이미지들의 주소는 다음과 같다
http://localhost:8080/list/N7lZkBpYYPVi4C0dbQTFACbSWTiH6I8h.png
http://localhost:8080/list/DJofU4r8cAwd0VtKTeKBROAq56Sw15PJ.png