/ SPRING

스프링 Client 파일 업로드(2)

스프링 목록

스프링 부트 목록


이번에 해야할것

  • 섬네일 생성
  • 생성된 섬네일 게시글 클릭시 보여주기
  • 올린 파일도 추가로 게시글 클릭시 보여주고, 받을수 있게 설정하기


1. pom.xml파일에 라이브러리 추가

<!-- 파일관련 / 썸네일라이브러리 -->
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.14</version>
</dependency>

What is Thumbnailator?(링크)


섬네일레이터는 Java용 섬네일 생성 라이브러리입니다.

축소판 그림 제작기를 사용해야 하는 이유 Java에서 고품질 미리 보기를 만드는 것은 상당히 어려운 작업일 수 있습니다.

Image I/O API, Java 2D API, 이미지 처리, 이미지 스케일링 기술 사용 방법 학습, …하지만 걱정하지 마십시오! 섬네일레이터가 이 모든 것을 해결해 줄 것입니다!

섬네일레이터는 외부 라이브러리에 종속되지 않는 단일 JAR 파일로 개발 및 배포가 쉽고 간단합니다. 메이븐 프로젝트에 쉽게 포함시킬 수 있도록 메이븐 중앙 저장소에서도 사용할 수 있다.

2. Controller에 썸네일 처리 코드 추가


Attention : 기존 리턴문 주석처리하기!

	@PostMapping("board/write")
	public ResponseEntity<?> write(@RequestPart(name = "letterFiles") List<MultipartFile> paramLetterFiles,
								   @RequestPart(name = "imageFile") MultipartFile paramImageFile, 
								   RepBoard repBoard) {

		log.info("요청전달데이터 title=" + repBoard.getBoardTitle() + ", content=" + repBoard.getBoardContent());
		log.info("letterFiles.size()=" + paramLetterFiles.size());
		log.info("imageFile.getSize()=" + paramImageFile.getSize());
		// 임시유저
		Customer testUser = new Customer();
		testUser.setId("id1");
		testUser.setName("김치");

		// 파일 경로생성
		if (!new File(saveDirectory).exists()) {
			log.info("업로드 실제경로생성");
			new File(saveDirectory).mkdirs();
		}		


                //전 글에서 보고 구현되어있어야함
		// 1.Add DATABASE              //
		// 2.Save List<letter> File     //
		// 3. Save image FiLe          //
                /////////////////////////////////



        // 4. Save Thumbnail imageFile
        //Code~

        // 5. 이미지 썸네일 프론트로 업로드 하기
        //Code~


		//아래 예시 코드 보고 주석칸에 코드 채워넣기


		//RETURN 주석처리 하기
		//return new ResponseEntity(HttpStatus.OK);
	}




4) 썸네일 이미지 저장하기

  • isSaveImageFileComplete 라는 boolean 값은
    //3. Save image FiLe 코드에 있음

이미지 저장이 성공되야, 썸네일을 만들수있기 때문에 true일경우 썸네일 생성

	// 4. Save Thumbnail imageFile
		String thumbnailName = "s_" + repBoard.getBoardNo() + paramImageFile.getOriginalFilename(); // 섬네일 파일명은
		File thumbnailFile = new File(saveDirectory, thumbnailName);
		try {
			//이미지 파일이 있어야 썸네일 생성가능
			if(!isSavedImageFileComplete) {throw new IOException();}

			FileOutputStream thumbnailOS = new FileOutputStream(thumbnailFile);
			InputStream imageFileIS = paramImageFile.getInputStream();
			Thumbnailator.createThumbnail(imageFileIS, thumbnailOS, s_width, s_height);
			log.info("섬네일파일 저장:" + thumbnailFile.getAbsolutePath() + ", 섬네일파일 크기:" + thumbnailFile.length());
		} catch (IOException e) {
			e.printStackTrace();
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}




5) 썸네일 프론트로 다시 전송해주기

        //5. 이미지 썸네일 프론트로 다시 전송해주기
		HttpHeaders responseHeaders = new HttpHeaders();
		try {
			responseHeaders.set(HttpHeaders.CONTENT_LENGTH, thumbnailFile.length() + "");
			responseHeaders.set(HttpHeaders.CONTENT_TYPE, Files.probeContentType(thumbnailFile.toPath()));
			responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=" + URLEncoder.encode("a", "UTF-8"));
			log.info("섬네일파일 다운로드");
			return new ResponseEntity<>(FileCopyUtils.copyToByteArray(thumbnailFile), responseHeaders, HttpStatus.OK);
		} catch (IOException e) {
			e.printStackTrace();
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}




완성 된 코드

    //멤버변수들
	private	String saveDirectory = "f:\\files";
	private int s_width=100;
	private int s_height=100;
	Logger log = Logger.getLogger(this.getClass())
    //



	@PostMapping("board/write")
	public ResponseEntity<?> write(@RequestPart(name = "letterFiles") List<MultipartFile> paramLetterFiles,
								   @RequestPart(name = "imageFile") MultipartFile paramImageFile, 
								   RepBoard repBoard) {

		log.info("요청전달데이터 title=" + repBoard.getBoardTitle() + ", content=" + repBoard.getBoardContent());
		log.info("letterFiles.size()=" + paramLetterFiles.size());
		log.info("imageFile.getSize()=" + paramImageFile.getSize());
		// 임시유저
		Customer testUser = new Customer();
		testUser.setId("id1");
		testUser.setName("김치");

		// 파일 경로생성
		if (!new File(saveDirectory).exists()) {
			log.info("업로드 실제경로생성");
			new File(saveDirectory).mkdirs();
		}

		
		// 1. Add DATABASE
		try {
			repBoard.setBoardC(testUser);
			service.add(repBoard);
		} catch (AddException e1) {
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}



		// 2.Save List<letter> File
		for (MultipartFile mf : paramLetterFiles) {
			log.info("파일크기: " + mf.getSize() + ", 파일이름:" + mf.getOriginalFilename());
			String mfFileName = repBoard.getBoardNo() + "_letter_" + UUID.randomUUID() + "_" + mf.getOriginalFilename();

			try {
				FileCopyUtils.copy(mf.getBytes(), new File(saveDirectory, mfFileName));
			} catch (IOException e) {
				e.printStackTrace();
				return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
			}
		}
		
		
		
		// 3. Save image FiLe
		boolean isSavedImageFileComplete = false;
		boolean isImageFile = paramImageFile.getContentType().contains("image/");

		if (!isImageFile){ 
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
		log.info("파일크기: " + paramImageFile.getSize() + ", 파일이름:" + paramImageFile.getOriginalFilename());
		String imageFileName = repBoard.getBoardNo() + "_image_" + UUID.randomUUID() + "_"
				+ paramImageFile.getOriginalFilename(); // 저장할 파일이름을 지정한다 ex) 글번호_image_XXXX_원본이름
														// ex) 0_image_ddf269da-3202-447a-a2c5-7ce395b63887_문어.png

		File createdImagefile = new File(saveDirectory, imageFileName);
		try {
			FileCopyUtils.copy(paramImageFile.getBytes(), createdImagefile);
			isSavedImageFileComplete = true;
			log.info("이미지파일 저장:" + createdImagefile.getAbsolutePath() + ", 이미지파일 크기:" + createdImagefile.length());
		} catch (IOException e1) {
			e1.getStackTrace();
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
		
		
		
		// 4. Save Thumbnail imageFile
		String thumbnailName = "s_" + repBoard.getBoardNo() + paramImageFile.getOriginalFilename(); // 섬네일 파일명은
		File thumbnailFile = new File(saveDirectory, thumbnailName);
		try {
			//이미지 파일이 있어야 썸네일 생성가능
			if(!isSavedImageFileComplete) {throw new IOException();}

			FileOutputStream thumbnailOS = new FileOutputStream(thumbnailFile);
			InputStream imageFileIS = paramImageFile.getInputStream();
			Thumbnailator.createThumbnail(imageFileIS, thumbnailOS, s_width, s_height);
			log.info("섬네일파일 저장:" + thumbnailFile.getAbsolutePath() + ", 섬네일파일 크기:" + thumbnailFile.length());
		} catch (IOException e) {
			e.printStackTrace();
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
		
		
		
        //5. 이미지 썸네일 프론트로 다시 전송해주기
		HttpHeaders responseHeaders = new HttpHeaders();
		try {
			responseHeaders.set(HttpHeaders.CONTENT_LENGTH, thumbnailFile.length() + "");
			responseHeaders.set(HttpHeaders.CONTENT_TYPE, Files.probeContentType(thumbnailFile.toPath()));
			responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=" + URLEncoder.encode("a", "UTF-8"));
			log.info("섬네일파일 다운로드");
			return new ResponseEntity<>(FileCopyUtils.copyToByteArray(thumbnailFile), responseHeaders, HttpStatus.OK);
		} catch (IOException e) {
			e.printStackTrace();
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}



        // 기존 RETURN 주석처리 하기
		//return new ResponseEntity(HttpStatus.OK);
	}



섬네일 제대로 저장하고 보내는 기능 작동하는지 테스트 하기





3. 유저가 저장한 파일 보여주기

프론트

  1. boarderinfo.html 수정( 게시글 클릭시 올린 파일칸 뚫기)
  2. boarderinfo.js 수정( 게시글 클릭시 올린 파일 읽어오기)

백엔드

  1. @getMapping(“board/info”)에 올린 파일도 추가해서 리턴
  2. 썸네일도 추가해서 리턴(글 수정예정 1/18일)
	@GetMapping("board/info")
	@ResponseBody
	public Object info(@RequestParam(defaultValue = "0") int boardNo) {
		final int BORDER_NO_INDEX = 0;

		try {
			RepBoard rb = service.findByNo(boardNo);
			Map<String, Object> info = new HashMap<String, Object>();

			info.put("boardNo", rb.getBoardNo());
			info.put("boardTitle", rb.getBoardTitle());
			info.put("boardC", rb.getBoardC());
			info.put("boardDt", rb.getBoardDt());
			info.put("boardContent", rb.getBoardContent());
			info.put("boardViewcount", rb.getBoardViewcount());
			
			//디렉토리에서 모든 파일 목록읽기
			File dir = new File(saveDirectory);


			//읽은 파일 목록에서 게시판 번호에 해당하는 자료만 뽑기
			List<String> filesNameList = new ArrayList<String>();
			for (String fileName : dir.list()) {
				String [] splitedName =fileName.split("_");
				if(splitedName[BORDER_NO_INDEX].equals(""+boardNo)) {
					filesNameList.add(fileName);
				}
			}
			info.put("files", filesNameList);

			
			return info;

		} catch (FindException e) {
			Map<String, Object> rm = new HashMap<String, Object>();
			rm.put("msg", e.getMessage());
			rm.put("status", 0);
			e.printStackTrace();

			return rm;
		}
	}

스프링 목록

스프링 부트 목록