MediaController
(test 용)
@RestController
@RequestMapping("media")
public class MediaController {
private static final Logger logger = LoggerFactory.getLogger(MediaController.class);
@PostMapping("test")
public void uploadMedia(
@RequestParam("file")MultipartFile file
) throws IOException {
String basePath="./media"; //저장될 기본 경로
File directory = new File(basePath);
if (!directory.exists()) directory.mkdir();
Path newFilePath = Path.of(basePath, file.getOriginalFilename());
try{
file.transferTo(newFilePath);
} catch (IOException e){
e.printStackTrace();
}
}
service
패키지 만들기, ModelService
인터페이스 정의
public interface ModelService {
void saveFile(MultipartFile file);
void saveFileBulk(MultipartFile[] files);
byte[] getFileAsBytes(String resourcePath);
}
LocalMediaService
public class LocalMediaService implements MedialService{
@Override
public void saveFile(MultipartFile file) {
}
@Override
public void saveFileBulk(MultipartFile[] files) {
}
@Override
public byte[] getFileAsBytes(String resourcePath) {
return new byte[0];
}
}
MediaDescriptorDto
public class MediaDescriptorDto {
private Integer status;
private String message;
private String originalName;
private String resourcePath;
=> Dto 정의해주었으니깐 Service에서도 dto 다루도록 수정
MediaService
public interface MedialService {
MediaDescriptorDto saveFile(MultipartFile file);
Collection<MediaDescriptorDto> saveFileBulk(MultipartFile[] files);
byte[] getFileAsBytes(String resourcePath);
}
LocalMediaService
도 위에 달라진 메소드들에 새롭게 오버라이드
LocalMediaService
(+)
@Service
public class LocalMediaService implements MedialService{
private static final Logger logger = LoggerFactory.getLogger(LocalMediaService.class);
//저장 경로 위해 추가
private final String basePath = "./media";
@Override
public MediaDescriptorDto saveFile(MultipartFile file) {
//미디어 파일이 하나만 들어오는 경우
return this.saveToDir(file);
}
@Override
public Collection<MediaDescriptorDto> saveFileBulk(MultipartFile[] files) {
//미디어 파일이 다수로 들어오는 경우
Collection<MediaDescriptorDto> resultList = new ArrayList<>();
for(MultipartFile file : files){
resultList.add(this.saveToDir(file));
}
return resultList;
}
@Override
public byte[] getFileAsBytes(String resourcePath) {
return new byte[0];
}
private MediaDescriptorDto saveToDir(MultipartFile file){
MediaDescriptorDto dto = new MediaDescriptorDto();
dto.setStatus(200);
dto.setOriginalName(file.getOriginalFilename());
try{
LocalDateTime now = LocalDateTime.now();
//날짜별로 파일을 나누기 위해 시간 받아오기
//now로 디렉토리를 생성하고, 거기에다 파일 저장할 것
String targetDir = Path.of(
basePath,
now.format(DateTimeFormatter.ISO_DATE)
).toString();
//현재 시간을 어떤 형식으로 나타내줄지 정하는 것
String newFileName = now.format(DateTimeFormatter.ofPattern("HHmmss"))
+ "_"
//업로드한 파일의 이름을 구한다.
+ file.getOriginalFilename();
File dirNow = new File(targetDir);
if(!dirNow.exists()) dirNow.mkdir();//디렉토리 없으면 만들기
//업로드한 파일 데이터를 지정한 파일에 저장
// MultipartFile.transferTo() 메서드를 사용
file.transferTo(Path.of(
targetDir,
newFileName
));
dto.setResourcePath(Path.of(
targetDir,
newFileName
).toString().substring(1));
return dto;
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage());
dto.setMessage("failed");
dto.setStatus(500);
return dto;
}
}
}
MediaController
@RestController
@RequestMapping("media")
public class MediaController {
private static final Logger logger = LoggerFactory.getLogger(MediaController.class);
private final MedialService medialService;
public MediaController(MedialService medialService){
this.medialService=medialService;
}
@PostMapping("upload")
public ResponseEntity<MediaDescriptorDto> uploadMedia(
@RequestParam("file") MultipartFile file
){
MediaDescriptorDto dto = this.medialService.saveFile(file);
return ResponseEntity
.status(dto.getStatus())
.body(dto);
}
@PostMapping("upload-bulk")
public ResponseEntity<Collection<MediaDescriptorDto>> uploadMediaBulk(
@RequestParam("file") MultipartFile[] files
//이름 동일한게 여러개 들어오면 알아서 배열로 인식
){
return ResponseEntity
.status(HttpStatus.MULTI_STATUS)
.body(this.medialService.saveFileBulk(files));
}
}
위와 같이 적절한 폴더, 파일명으로 저장됨
이제 get으로 가져왔을 때 binary로 보이는게 아닌 사진 파일로 보이도록 코드 refactor
MediaController
@GetMapping("**")
public byte[] staticLikeEndpoint(
HttpServletRequest request, HttpServletResponse response
){
response.setHeader("Content-type", MediaType.IMAGE_PNG_VALUE);
//미디어타입과 같은 확장자 정해줄 때 잘 정해줘야 함
return this.medialService.getFileAsBytes(request.getRequestURI().split("media")[1]);
}
MediaService
@Override
public byte[] getFileAsBytes(String resourcePath) {
try{
return Files.readAllBytes(Path.of(basePath, resourcePath));
} catch (IOException e) {
e.printStackTrace();
//읽는 과정에서 에러
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
}
MediaController
@GetMapping("**")
public ResponseEntity<byte[]> staticLikeEndpoint(
HttpServletRequest request){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
//미디어타입과 같은 확장자 정해줄 때 잘 정해줘야 함
return new ResponseEntity<>(
this.medialService.getFileAsBytes(request.getRequestURI().split("media")[1]),
headers,
HttpStatus.OK
);
}
private FileOutputStream fos = null;
public String uploadResult(@RequestParam("selFile") MultipartFile mFile) throws Exception, IOException {
String fileExtension = mFile.getOriginalFilename().substring(mFile.getOriginalFilename().lastIndexOf("."));
String storedFileName = UUID.randomUUID().toString().replaceAll("-", "") + fileExtension;
String filePath = "C:\\eclipse\\workspace\\memPid\\src\\main\\webapp\\resources\\";
File file = new File(filePath + storedFileName);
//첫 번째 방법, MultipatrFile클래스의 transferTo()를 사용하여 업로드하려는 파일을 특정파일로 저장
//MultipartFile.transferTo(File file) - Byte형태의 데이터를 File객체에 설정한 파일 경로에 전송한다.
mFile.transferTo(file);
//두 번째 방법, MultipatrFile클래스의 getBytes()로 multipartFile의 데이터를 바이트배열로 추출한 후, FileOutputStream클래스의 write()로 파일을 저장
try {
//MultipatrFile클래스의 getBytes()를 사용해서 multipartFile의 데이터를 바이트배열로 추출
byte fileData[] = mFile.getBytes();
fos = new FileOutputStream(filePath + mFile.getOriginalFilename());
//FileOutputStream클래스의 write()로 파일을 filePath에 저장
fos.write(fileData);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(fos != null) {
fos.close();
}
}
return "upload_result";
}
화면
<!--화면단(JSP)-->
<form action="submitReport1" method="POST" enctype="multipart/form-data">
학번 : <input type="text" name="studentNumber" /><br/>
리포트 파일 : <input type="file" name="reportFile" /><br/>
<input type="submit" />
</form>
서비스
String filePath , //파일을 저장할 경로
String originalFile, //원본 파일명
String originalFileExtension, //원본파일의 확장자명
String storedFileName, //filePath/DB에 저장할 파일명
MultipartFile multipartFile, //화면단에서 전달되는 파일 받을 객체
File file //java.io.File //전달받은 파일을 저장할 때 사용하는 객체
String filePath =
// "C:\\Users\\FUTURE\\Documents\\hkedu_project\\final_project\\src\\main\\webapp\\WEB-INF\\resource\\";
"C:\\Users\\HKEDU\\Documents\\hkedu_project\\final_project\\src\\main\\webapp\\WEB-INF\\resource\\";
// "C:\\Users\\HKEDU\\Documents\\hkedu_project\\final_project\\src\\main\\webapp\\WEB-INF\\resource\\";
// "C:\\Users\\hotelalpha\\Documents\\hkedu_project\\final_project\\src\\main\\webapp\\WEB-INF\\resource\\";
File file = New File(filePath);
화면단에서 업로드한 파일(foodImage)을 전달받아서 지정 경로에 저장하고, 파일의 정보를 DB에 저장하는 방법
MultipartFile multipartFile = foodRegCommand.getFoodImage();
//*커맨드객체 사용 시 커맨드객체 내의 필드타입은 MultipartFile이어야한다.
//private MultipartFile report;
@RequestParam
어노테이션과 MultipartFile 타입의 파라미터를 이용public String submitReport1(@RequestParam("studentNumber") String studentNumber, @RequestParam("report") MultipartFile multipartFile) throws IOException {
//command객체가 아닌 request로 submit한 값 받아오기
//studentNumber - submissionForm의 속성 name
public String submitReport2(MultipartHttpServletRequest request) {
String studentNumber = request.getParameter("studentNumber");
MultipartFile report = request.getFile("report");
//파일명
String originalFile = multipartFile.getOriginalFilename();
//파일명 중 확장자만 추출
//fileuploadtest.doc
//lastIndexOf(".") = 14(index는 0번부터)
//substring(14) = .doc
String originalFileExtension = originalFile.substring(originalFile.lastIndexOf("."));
//업무에서 사용하는 리눅스, UNIX는 한글지원이 안 되는 운영체제
//파일업로드시 파일명은 ASCII코드로 저장되므로, 한글명으로 저장 필요
//UUID클래스 - (특수문자를 포함한)문자를 랜덤으로 생성 "-"라면 생략으로 대체
String storedFileName = UUID.randomUUID().toString().replaceAll("-", "") + originalFileExtension;
//파일을 저장하기 위한 File객체 생성
//java.io.File
File file = new File(filePath + storedFileName);
//업로드요청으로 전달받은 파일을 위에서 설정한 특정 경로에 특정 파일명으로 저장
multiFile.transferTo(file);
//전달받아 저장한 파일의 이름 및 저장된 경로, 용량을 DB에 저장
foodReview = new FoodReview();
foodReview.setMemberEmail(memberEmail);
foodReview.setFoodNo(foodReviewWriteCommand.getFoodNo());
foodReview.setSellerEmail(foodReviewWriteCommand.getSellerEmail());
...
foodReview.setFoodReviewSize(multiFile.getSize());
foodReview.setFoodReviewOriginal(originalFile);
foodReview.setFoodReviewStored(storedFileName);
int k = foodRepository.insertFoodReview(foodReview);