user.service
         UserService.java (Interface)
         ObjectStorageService.java(Interface)


user.service.impl
         UserServiceImpl.java
         NCPObjectStorage.java

package user.service.impl;

import org.springframework.stereotype.Service;

import user.service.ObjectStorageService;

@Service
public class NCPObjectStorage implements ObjectStorageService {

}

spring
       mybatis-config.xml ====> 제거
       db.properties
       navar.properties

ncp.accessKey=
ncp.secretKey=
ncp.regionName=kr-standard
ncp.endPoint=https://kr.object.ncloudstorage.com

UserUploadController.java

//imageFileName = UUID.randomUUID().toString(); 주석걸기

 

@Autowired
private ObjectStorageService objectStorageService;

private String bucketName = "bitcamp-9th-bucket-132";

 


//네이버 클라우드 Object Storage-------------------------------
imageFileName = objectStorageService.uploadFile(bucketName, "storage/", img);

@Controller
@RequestMapping(value="user")
public class UserUploadController {
	@Autowired
	private UserUploadService userUploadService;
	@Autowired
	private ObjectStorageService objectStorageService;
	
	private String bucketName = "bitcamp-9th-bucket-132";
		for(MultipartFile img: list) {
			//imageFileName = UUID.randomUUID().toString();
			
			//네이버 클라우드 Object Storage-------------------------------
			imageFileName = objectStorageService.uploadFile(bucketName, "storage/", img);

ObjectStorageService.java

package user.service;

import org.springframework.web.multipart.MultipartFile;

public interface ObjectStorageService {

	public String uploadFile(String bucketName, String string, MultipartFile img);

}

NCPObjectStorage.java

package user.service.impl;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import user.service.ObjectStorageService;

@Service
public class NCPObjectStorage implements ObjectStorageService {

	@Override
	public String uploadFile(String bucketName, String directoryPath, MultipartFile img) {
		// TODO Auto-generated method stub
		return null;
	}

}

aws java sdk s3

pom.xml

    <!-- AWS -->
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-s3</artifactId>
        <version>1.12.610</version>
    </dependency>

파일 업로드

spring.conf
      SpringConfiguration.java
      NaverConfiguration.java

package spring.conf;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import lombok.Getter;
import lombok.Setter;

@Configuration
@PropertySource("classpath:spring/naver.properties")
@Getter
@Setter
public class NaverConfiguration {
	private @Value("${ncp.accessKey}") String accessKey; //접근할 수 있는 키값
	private @Value("${ncp.secretKey}") String secretKey; //보안 키값
	private @Value("${ncp.regionName}") String regionName;
	private @Value("${ncp.endPoint}") String endPoint;
}

NCPObjectStorage.java

package user.service.impl;

import java.io.InputStream;
import java.util.UUID;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;

import spring.conf.NaverConfiguration;
import user.service.ObjectStorageService;

@Service
public class NCPObjectStorage implements ObjectStorageService {
	final AmazonS3 s3;
	
	public NCPObjectStorage(NaverConfiguration naverConfiguration) {
		s3 = AmazonS3ClientBuilder
				.standard()
				.withEndpointConfiguration(
						new AwsClientBuilder.
								EndpointConfiguration(naverConfiguration.getEndPoint(), 
													  naverConfiguration.getRegionName()))
				.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(naverConfiguration.getAccessKey(), naverConfiguration.getSecretKey())))
				.build();
	}
	
	@Override
	public String uploadFile(String bucketName, String directoryPath, MultipartFile img) {
		try(InputStream inputStream = img.getInputStream()){
			String imageFileName = UUID.randomUUID().toString();
			//String imageFileName = img.getOriginalFilename(); 둘 중 뭐로 올릴지는 우리가 선택 !
			
			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentType(img.getContentType());
			
			PutObjectRequest putObjectRequest =
					new PutObjectRequest(bucketName, 
									     directoryPath + imageFileName,
									     inputStream,
									     objectMetadata).withCannedAcl(CannedAccessControlList.PublicRead); //리소스에 대한 접근 권한
					//모든 사용자가 객체를 읽을 수 있지만, 수정과 삭제는 불가능하다.
			
			s3.putObject(putObjectRequest);
			
			return imageFileName;
		}catch (Exception e) {
			throw new RuntimeException("파일 업로드 에러");
		}
	}

}

db.properties -- Naver Cloud 주석 풀어주기 !


userUpload.sql

use study db;
create table userUpload (
seq int(10) primary key auto_increment,
imageName varchar(50),
imageContent varchar(4000),
imageFileName varchar(100) not null,
imageOriginalFileName varchar(100) not null);

uploadList.jsp

 <%-- <img src="/spring2/storage/${userUploadDTO.imageOriginalFileName}" --%> 주석걸고

경로바꾸기

<img src=

"https://kr.object.ncloudstorage.com/bitcamp-9th-bucket-132/storage/${userUploadDTO.imageFileName}"

    <td>
        <%-- <img src="/spring2/storage/${userUploadDTO.imageOriginalFileName}" width="100" height="100" alt="${userUploadDTO.imageName}"> --%>
       <%-- Object Storage --%>
       <img src="https://kr.object.ncloudstorage.com/bitcamp-9th-bucket-132/storage/${userUploadDTO.imageFileName}" width="100" height="100" alt="${userUploadDTO.imageName}">
	</td>

 

select * from userUpload;


파일 출력

uploadList.jsp

<a href="/spring2/user/uploadView?seq=${userUploadDTO.seq}">

        <td>
            <a href="/spring2/user/uploadView?seq=${userUploadDTO.seq}">
                <%-- <img src="/spring2/storage/${userUploadDTO.imageOriginalFileName}" width="100" height="100" alt="${userUploadDTO.imageName}"> --%>
                <%-- Object Storage --%>
                <img src="https://kr.object.ncloudstorage.com/bitcamp-9th-bucket-132/storage/${userUploadDTO.imageFileName}" width="100" height="100" alt="${userUploadDTO.imageName}">
            </a>
        </td>

UserUploadController.java

	@RequestMapping(value = "uploadView")
	public String uploadView(@RequestParam String seq, Model map) {
		UserUploadDTO userUploadDTO = userUploadService.getUploadDTO(seq);
		return "/upload/uploadView";
	}

 


UserUploadService.java

public UserUploadDTO getUploadDTO(String seq);

package user.service;

import java.util.List;

import user.bean.UserUploadDTO;

public interface UserUploadService {

	public void upload(List<UserUploadDTO> imageUploadList);

	public List<UserUploadDTO> uploadList();

	public UserUploadDTO getUploadDTO(String seq);

}

UserUploadServiceImpl.java

@Override
public UserUploadDTO getUploadDTO(String seq) {
        return userUploadDAO.getUploadDTO(seq);
}

package user.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import user.bean.UserUploadDTO;
import user.dao.UserUploadDAO;
import user.service.UserUploadService;

@Service
public class UserUploadServiceImpl implements UserUploadService {
	@Autowired
	private UserUploadDAO userUploadDAO;
	
	@Override
	public void upload(List<UserUploadDTO> imageUploadList) {
		userUploadDAO.upload(imageUploadList);
	}

	@Override
	public List<UserUploadDTO> uploadList() {
		return userUploadDAO.uploadList();
	}

	@Override
	public UserUploadDTO getUploadDTO(String seq) {
		return userUploadDAO.getUploadDTO(seq);
	}

}

UserUploadDAO.java

public UserUploadDTO getUploadDTO(String seq);

package user.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import user.bean.UserUploadDTO;

@Mapper
public interface UserUploadDAO {

	public void upload(List<UserUploadDTO> imageUploadList);

	List<UserUploadDTO> uploadList();

	public UserUploadDTO getUploadDTO(String seq);

}

userUploadMapper.xml

    <!-- 1개의 정보 -->
    <select id="getUploadDTO" parameterType="String" resultType="userUploadDTO">
    	 select * from userUpload where seq = #{seq}
    </select>

 

seq는 원래 int형인데 String타입으로 오면 원래 비교 안해주는데 간단한경우에는 알아서 해결해준다.

대신 복잡해지면 error 떨어진다.

이게 싫으면 애초에 int형으로 보내면 된다.

(근데 나중에 이 부분 error 떠서 다 int형으로 바꿔줬다,,,,)


UserUploadController.java

	@RequestMapping(value = "uploadView")
	public String uploadView(@RequestParam String seq, Model model) {
		UserUploadDTO userUploadDTO = userUploadService.getUploadDTO(seq);
		model.addAttribute("userUploadDTO", userUploadDTO);
		
		return "/upload/uploadView";
	}

uploadView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<table border="1">
	<tr>
		<td rowspan="3">
			<img src="https://kr.object.ncloudstorage.com/bitcamp-9th-bucket-132/storage/${userUploadDTO.imageFileName}" alt="${userUploadDTO.imageFileName }" />
		</td>
		<td width="250" style="text-indent: 10pt;">번호 : ${userUploadDTO.seq }</td>
	</tr>
	
	<tr>
		<td>상품명 : ${userUploadDTO.imageName }</td>
	</tr>
	
	<tr>
		<td>파일명 : ${userUploadDTO.imageOriginalFileName } </td>
	</tr>
	
	<tr>
		<td colspan="2" height="200">
			 <pre>${userUploadDTO.imageContent }</pre>
		</td>
	</tr>
</table>
</body>
</html>

 


파일 수정

uploadView.jsp

<div style="margin-top: 5px;">
	<input type="button" value="목록" onclick="location.href='/spring2/user/uploadList'" />
	<input type="button" value="수정" onclick="location.href='/spring2/user/uploadUpdateForm?seq=${userUploadDTO.seq }'" />
</div>

UserUploadController.java

	@RequestMapping(value = "uploadUpdateForm")
	public String uploadUpdateForm(@RequestParam String seq, Model model) {
		UserUploadDTO userUploadDTO = userUploadService.getUploadDTO(seq);
		model.addAttribute("userUploadDTO", userUploadDTO);
		
		return "/upload/uploadUpdateForm";
	}

uploadUpdateForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>이미지 수정</title>
    <link rel="stylesheet" href="../css/uploadFormList.css"> 
</head>
<body>
    <div class="container">
        <h2>이미지 수정</h2>
        <form id="uploadUpdateForm">
            <input type="hidden" name="seq" value="${userUploadDTO.seq}">
            
            <table>
                <tr>
                    <td>상품명</td>
                    <td>
                        <input type="text" name="imageName" value="${userUploadDTO.imageName}" required>
                    </td>
                </tr>

                <tr>
                    <td>상품내용</td>
                    <td>
                        <textarea name="imageContent" rows="5" cols="40">${userUploadDTO.imageContent}</textarea>
                    </td>
                </tr>               
                
                <tr>
                    <td colspan="2">
                    	
                    	<img id="camera" id="img" name="img" alt="카메라" src="../image/camera.png" width="50" height="50">
                    	<span id="showImageList">
                    		<img src="https://kr.object.ncloudstorage.com/bitcamp-9th-bucket-132/storage/${userUploadDTO.imageFileName}" width="70" height="70" alt="${userUploadDTO.imageName}" />
                    	</span>
                        <input type="file" id="img" name="img" style="visibility: hidden;">
                    </td>
                </tr>

                <tr>
                    <td colspan="2">
                        <input type="button" value="수정" id="uploadUpdateBtn"  class="button">
                        <input type="button" value="취소" onclick="location.href='/spring2/user/uploadList'" class="button">
                    </td>
                </tr>
            </table>
        </form>
    </div>
<script type="text/javascript" src="http://code.jquery.com/jquery-3.7.1.min.js"></script>
<script type="text/javascript" src="../js/uploadUpdate.js"></script>
<script type="text/javascript">
$('#camera').click(function(){
	$('#img').trigger('click'); //강제 이벤트 발생	
});

//이미지 미리보기
$('#img').change(function(){
	$('#showImageList').empty();
	
	for(var i=0; i<this.files.length; i++){
		readURL(this.files[i]);
	}
});

function readURL(file){
	var reader = new FileReader();
	
	var show;
	reader.onload = function(e){
		var img = document.createElement('img');
		img.src = e.target.result;
		img.width = 70;
		img.height = 70;
		
		$('#showImageList').append(img);
	}
	
	reader.readAsDataURL(file);
}
</script>
</body>
</html>


uploadUpdate.js

$(function(){
	$('#uploadUpdateBtn').click(function(){
		let formData = new FormData($('#uploadUpdateForm')[0]);
		
		$.ajax({
			type: 'post',
			enctype: 'multipart/form-data',
			processData: false,
			contentType: false,
			url: '/spring2/user/uploadUpdate',
			data: formData,
			success: function(data){
				location.href = "/spring2/user/uploadList";
			},
			error: function(e){
				console.log(e);
			}
			
		}); //$.ajax
	});
});

UserUploadController.java

	@RequestMapping(value = "uploadUpdate", produces = "text/html; charset=UTF-8")
	@ResponseBody
	public String uploadUpdate(@ModelAttribute UserUploadDTO userUploadDTO,
							   @RequestParam("img") MultipartFile img) {
		userUploadService.uploadUpdate(userUploadDTO, img);
		return "이미지 수정 완료";
	}

 


UserUploadService.java

public void uploadUpdate(UserUploadDTO userUploadDTO, MultipartFile img);

package user.service;

import java.util.List;

import org.springframework.web.multipart.MultipartFile;

import user.bean.UserUploadDTO;

public interface UserUploadService {

	public void upload(List<UserUploadDTO> imageUploadList);

	public List<UserUploadDTO> uploadList();

	public UserUploadDTO getUploadDTO(String seq);

	public void uploadUpdate(UserUploadDTO userUploadDTO, MultipartFile img);

}

//실제폴더
String filePath = session.getServletContext().getRealPath("WEB-INF/storage");
System.out.println("실제 폴더 = " + filePath);

 

-- Controller에서 해도되고 service에서 해도된다. 이번엔 service에서 해보자 !!

 

UserUploadServiceImpl.java

@Autowired
private HttpSession session;

 

Object Storage(NCP)는 이미지를 덮어쓰지 않는다.

DB에서 seq에 해당하는 imageFileName을 꺼내와서 Object Storage(NCP)의 이미지를 삭제하고,

새로운 이미지를 올린다.

 

UserUploadServiceImpl.java

	@Override
	public void uploadUpdate(UserUploadDTO userUploadDTO, MultipartFile img) {
		//실제폴더
		String filePath = session.getServletContext().getRealPath("WEB-INF/storage");
		System.out.println("실제 폴더 = " + filePath);
		
		//Object Storage(NCP)는 이미 지를 덮어쓰지 않는다.
		//DB에서 seq에 해당하는 imageFileName을 꺼내와서 Object Storage(NCP)의 이미지를 삭제하고,
		//새로운 이미지를 올린다.
		String imageFileName = userUploadDAO.getImageFileName(userUploadDTO.getSeq());
		System.out.println(imageFileName);
    }

 

select imageFileName from userUpload where seq = ?;


UserUploadDAO.java

public String getImageFileName(int seq);

package user.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import user.bean.UserUploadDTO;

@Mapper
public interface UserUploadDAO {

	public void upload(List<UserUploadDTO> imageUploadList);

	List<UserUploadDTO> uploadList();

	public UserUploadDTO getUploadDTO(String seq);

	public String getImageFileName(int seq);

}

 


userUploadMapper.xml

    <!-- imageFileName 얻기 -->
    <select id="getImageFileName" parameterType="String" resultType="String">
    	select imageFileName from userUpload where seq = #{seq};
    </select>

UserUploadServiceImpl.java

NCP에 있는 이미지 삭제하고 새로운 이미지 올리는 작업이 필요하다 !

		//Object Storage(NCP) 이미지 삭제
		objectStorageService.deleteFile(bucketName, "storage/", imageFileName);
		
		//Object Storage(NCP) 새로운 이미지 올리기
		imageFileName = objectStorageService.uploadFile(bucketName, "storage/", img);

ObjectStorageService.java

public void deleteFile(String bucketName, String string, String imageFileName);

package user.service;

import org.springframework.web.multipart.MultipartFile;

public interface ObjectStorageService {

	public String uploadFile(String bucketName, String string, MultipartFile img);

	public void deleteFile(String bucketName, String string, String imageFileName);

}

NCPObjectStorage.java

	@Override
	public void deleteFile(String bucketName, String directoryPath, String imageFileName) {
		s3.deleteObject(bucketName, directoryPath + imageFileName);
	}

 


UserUploadServiceImpl.java

		String imageOriginalFileName = img.getOriginalFilename();	
		File file = new File(filePath, imageOriginalFileName);
		
		try {
			img.transferTo(file);
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		userUploadDTO.setImageFileName(imageFileName);
		userUploadDTO.setImageOriginalFileName(imageOriginalFileName);
		
		//DB
		userUploadDAO.uploadUpdate(userUploadDTO);
	}

UserUploadDAO.java

public void uploadUpdate(UserUploadDTO userUploadDTO);

package user.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import user.bean.UserUploadDTO;

@Mapper
public interface UserUploadDAO {

	public void upload(List<UserUploadDTO> imageUploadList);

	List<UserUploadDTO> uploadList();

	public UserUploadDTO getUploadDTO(String seq);

	public String getImageFileName(int seq);

	public void uploadUpdate(UserUploadDTO userUploadDTO);

}

userUploadMapper.xml

    <!-- 수정 -->
    <update id="uploadUpdate" parameterType="userUploadDTO">
    	update userUpload set imageName=#{imageName},
    						  imageContent=#{imageContent},
    	                      imageFileName=#{imageFileName},
    	                      imageOriginalFileName=#{imageOriginalFileName}
    	where seq=#{seq}
    </update>

이미지 수정 안 하고 올릴 때 

이제 이미지를 수정안하고 올려버리면 null값이 저장되면서 기존 사진이 다시 안 불러와지고 error가 뜨게 된다.

그러므로 원래 db에서 데이터를 가져와서 그 값을 다시 넣어주는 작업이 필요하다 !!!

MultipartFile img 여기서 img의 size가 0일 경우와 0이 아닌 경우를 확인 후 코드를 if문으로 해서 나눠야한다 !!

 

UserUploadServiceImpl.java

	@Override
	public void uploadUpdate(UserUploadDTO userUploadDTO, MultipartFile img) {
		//실제폴더
		String filePath = session.getServletContext().getRealPath("WEB-INF/storage");
		System.out.println("실제 폴더 = " + filePath);

		System.out.println("img = " + img);
		
		//Object Storage(NCP)는 이미 지를 덮어쓰지 않는다.
		//DB에서 seq에 해당하는 imageFileName을 꺼내와서 Object Storage(NCP)의 이미지를 삭제하고,
		//새로운 이미지를 올린다.
		//String imageFileName = userUploadDAO.getImageFileName(userUploadDTO.getSeq());
		UserUploadDTO dto = userUploadDAO.getUploadDTO(userUploadDTO.getSeq());
		System.out.println("imageFileName = " + dto.getImageFileName());
		System.out.println("size = " + img.getSize());
	
		String imageFileName;
		String imageOriginalFileName;
		
		if(img.getSize() != 0) {
			//Object Storage(NCP) 이미지 삭제
			objectStorageService.deleteFile(bucketName, "storage/", dto.getImageFileName());
			
			//Object Storage(NCP) 새로운 이미지 올리기
			imageFileName = objectStorageService.uploadFile(bucketName, "storage/", img);
			
			imageOriginalFileName = img.getOriginalFilename();	
			File file = new File(filePath, imageOriginalFileName);
			
			try {
				img.transferTo(file);
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println(dto.getImageFileName() + ", " + dto.getImageOriginalFileName());
			imageFileName = dto.getImageFileName();
			imageOriginalFileName = dto.getImageOriginalFileName();
		}
		
		
		userUploadDTO.setImageFileName(imageFileName);
		userUploadDTO.setImageOriginalFileName(imageOriginalFileName);
		
		//DB
		userUploadDAO.uploadUpdate(userUploadDTO);
	}

 

 

summ.n