Spring - Ajax 사용하여 이미지 , 파일 업로드 구현하기 (feat. AWS S3)

2021. 5. 17. 21:21Java/Spring

반응형

Ajax를 이용하여 이미지 및 파일을 업로드 하는 방법을 알아보도록 하겠습니다.

 

본 글에서 이미지 저장은 로컬 저장소가 아닌 AWS S3 를 이용하여 저장을 합니다.

 

 

먼저 ajax에서 이미지 입력을 받아서 백엔드(스프링)으로 넘겨줘야 합니다.

 

이때 formData 라는 객체를 사용하게 됩니다.

 

var formData = new FormData();

해당 객체를 통해 파일 및 일반 데이터(텍스트)를 아작스에 담아서 넘길 수 있습니다.

 

public class testDto {
	private String test1;
	private String test2;
	private MultipartFile[] test3;
	
	public String getTest1() {
		return test1;
	}
	public void setTest1(String test1) {
		this.test1 = test1;
	}
	public String getTest2() {
		return test2;
	}
	public void setTest2(String test2) {
		this.test2 = test2;
	}
	public MultipartFile[] getTest3() {
		return test3;
	}
	public void setTest3(MultipartFile[] test3) {
		this.test3 = test3;
	}
	
	
}

 

DTO가 위와 같을 때 아래와 같이 데이터를 formData에 append로 각 dto의 변수 명과 통일 시켜 담아보냅니다.

 

파일을 dto에 담을 때는 단일 파일 전송이라면 자료형을 MultipartFile로 주고 파일이 여러개일 경우에는 MultipartFile[] 로 배열로 작성합니다.

 

<%@ 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>
<input id="test1" name="test1">
<input id="test2" name="test2">
<input id="test3" name="test3" type="file">

<button onclick="send()">전송</button>

<script>
function send(){
	var test3 = $('input[name="test3"]').get(0).files[0];
	var test1 = $("#test1").val()
	var test2 = $("#test2").val()
	var formData = new FormData();
	formData.append('test1', test1);
	formData.append('test2', test2);
	formData.append('test3', test3);

	$.ajax({
		type : 'POST',
		url : '/test/testPro.do',
		processData:false,
		contentType: false,
	    data: formData,
		success : function(json){
			alert("등록되었습니다.");
			
		},
		error: function(xhr, status, error){
			alert("가입에 실패했습니다."+error);
		}
	});
}


</script>
</body>
</html>

ajax 를 작성시에는 processData:false,contentType: false 을 꼭 해줘야합니다.

 

 

해당 데이터를 받는 부분은 아래와 같이 받을 수 있습니다.

@RequestMapping(value="/testPro.do", method=RequestMethod.POST)
	public String testPro(testDto td) throws SQLException, Exception {
		System.out.println(td.getTest1());
		System.out.println(td.getTest2());
		ArrayList fileNames = filemanagement.FileUploader(td.getTest3());
		return "ok";
	}

위와 같이 td에 testDto 가 담겨서 옵니다.

 

이제 해당 이미지 파일을 업로드하는 util 처리를 할 차례입니다.

 

util에서는 AWS S3 를 이용하기 때문에 해당 S3 접근 및 업로드에 대한 부분이 필요합니다.

@Component
public class S3Uploader {

	
    public static String accessKey;
    public static String secretKey;
	
	
	@Value("${aws.secretKey}")
	public void setSecret(String value) {
		secretKey = value;
	}
	@Value("${aws.accessKey}")
	public void setClient(String value) {
		accessKey = value;
	}
    
    
	private AmazonS3 conn;

	public void S3Uploader() {
		System.out.println("accessKey ==>"+accessKey);
		System.out.println("secretKey ==>"+secretKey);
		AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
		ClientConfiguration clientConfig = new ClientConfiguration();
		clientConfig.setProtocol(Protocol.HTTP);
		this.conn = new AmazonS3Client(credentials, clientConfig);
		conn.setEndpoint("s3.ap-northeast-2.amazonaws.com"); // 엔드포인트 설정 [ 아시아 태평양 서울 ]
	}

	// 버킷 리스트를 가져오는 메서드이다.
	public List<Bucket> getBucketList() {
		return conn.listBuckets();
	}

	// 버킷을 생성하는 메서드이다.
	public Bucket createBucket(String bucketName) {
		return conn.createBucket(bucketName);
	}

	// 폴더 생성 (폴더는 파일명 뒤에 "/"를 붙여야한다.)
	public void createFolder(String bucketName, String folderName) {
		conn.putObject(bucketName, folderName + "/", new ByteArrayInputStream(new byte[0]), new ObjectMetadata());
	}
	
	// 파일 업로드
	public void fileUpload(String bucketName, String fileName, MultipartFile file) throws IOException {
		byte [] fileData=file.getBytes();
		
		String filePath = (fileName).replace(File.separatorChar, '/'); // 파일 구별자를 `/`로 설정(\->/) 이게 기존에 / 였어도 넘어오면서 \로 바뀌는 거같다.
		ObjectMetadata metaData = new ObjectMetadata();

		metaData.setContentLength(fileData.length);   //메타데이터 설정 -->원래는 128kB까지 업로드 가능했으나 파일크기만큼 버퍼를 설정시켰다.
	    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileData); //파일 넣음

		conn.putObject(bucketName, filePath, byteArrayInputStream, metaData);
		
	}
	// 파일 업로드
	public void fileUpload(String bucketName, String fileName, byte[] fileData) throws FileNotFoundException {

		String filePath = (fileName).replace(File.separatorChar, '/'); // 파일 구별자를 `/`로 설정(\->/) 이게 기존에 / 였어도 넘어오면서 \로 바뀌는 거같다.
		ObjectMetadata metaData = new ObjectMetadata();

		metaData.setContentLength(fileData.length);   //메타데이터 설정 -->원래는 128kB까지 업로드 가능했으나 파일크기만큼 버퍼를 설정시켰다.
	    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileData); //파일 넣음

		conn.putObject(bucketName, filePath, byteArrayInputStream, metaData);

	}
	// 파일 삭제
	public void fileDelete(String bucketName, String fileName) {
		String imgName = (fileName).replace(File.separatorChar, '/');
		conn.deleteObject(bucketName, imgName);
		System.out.println("삭제성공");
	}

	// 파일 URL
	public String getFileURL(String bucketName, String fileName) {
		System.out.println("넘어오는 파일명 : "+fileName);
		String imgName = (fileName).replace(File.separatorChar, '/');
		return conn.generatePresignedUrl(new GeneratePresignedUrlRequest(bucketName, imgName)).toString();
	}
}

AWS S3 생성 및 키 발급은 추후에 올라옵니다.

 

먼저 위와 같이 S3Upload.java를 만들어 줍니다.

 

public static String accessKey;
    public static String secretKey;
	
	
	@Value("${aws.secretKey}")
	public void setSecret(String value) {
		secretKey = value;
	}
	@Value("${aws.accessKey}")
	public void setClient(String value) {
		accessKey = value;
	}

해당 코드를 통해 접근 및 보안키를 넣어 S3에 접근이 가능하게 합니다.

 

public void S3Uploaders() {
		AWSCredentials credentials = new BasicAWSCredentials("accessKey", "secretKey");
		ClientConfiguration clientConfig = new ClientConfiguration();
		clientConfig.setProtocol(Protocol.HTTP);
		this.conn = new AmazonS3Client(credentials, clientConfig);
		conn.setEndpoint("s3.ap-northeast-2.amazonaws.com"); // 엔드포인트 설정 [ 아시아 태평양 서울 ]
	}

해당 메소드를 호출하면 accessKey와 secretKey를 받아서 S3에 접근을 합니다.

 

파일 업로드 전에 해당 메소드를 실행해주면 됩낟.

 

그리고 아래 코드는 저장 버킷 명, 파일 이름, 파일을 받아서 해당 파일을 aws S3에 업로드 하는 역할을 합니다.

 

public void fileUpload(String bucketName, String fileName, MultipartFile file) throws IOException {
		byte [] fileData=file.getBytes();
		String filePath = (fileName).replace(File.separatorChar, '/'); // 파일 구별자를 `/`로 설정(\->/) 이게 기존에 / 였어도 넘어오면서 \로 바뀌는 거같다.
		ObjectMetadata metaData = new ObjectMetadata();

		metaData.setContentLength(fileData.length);   //메타데이터 설정 -->원래는 128kB까지 업로드 가능했으나 파일크기만큼 버퍼를 설정시켰다.
	    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileData); //파일 넣음

		conn.putObject(bucketName, filePath, byteArrayInputStream, metaData);

	}

위와 같이 모두 작성을 하였으면 준비는 다 끝났습니다.

 

 

FileUploader를 아래와 같이 작성해줍니다.

import java.io.IOException;
import java.util.ArrayList;
import com.amazonaws.services.s3.AmazonS3Client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class FileManagement {

	@Autowired
	private S3Uploader S3Uploader;
	
	public ArrayList FileUploader(MultipartFile[] files) throws IOException {
		ArrayList filelist = new ArrayList();
		String FileNames ="";
		S3Uploader.S3Uploaders();
		  for (MultipartFile mf : files) {
			    
	            String originFileName = mf.getOriginalFilename(); // 원본 파일 명
	            long fileSize = mf.getSize(); // 파일 사이즈

	            System.out.println("originFileName : " + originFileName);
	            System.out.println("fileSize : " + fileSize);
	            S3Uploader.fileUpload("cookingcoding",originFileName,mf);
	            String safeFile =System.currentTimeMillis() + originFileName;
	            
	            FileNames = FileNames+","+safeFile; 
	            filelist.add(originFileName);
	            try {
	            //	File f1 = new File(filepath+safeFile);
	            //    mf.transferTo(f1);
	            } catch (IllegalStateException e) {
	                // TODO Auto-generated catch block
	                e.printStackTrace();
	            }
	        }
		
		return filelist;
	}
	
}
S3Uploader.S3Uploaders();

위 코드를 통해 S3 사용을 선언합니다.

 

그리고 파일을 배열로 받아주기 때문에 반복문을 돌아 파일의 정보를 꺼내 S3에 fileUpload를 통해 cookingcoding이라는 버킷에 저장합니다.

 

그리고 저장한 파일의 이름들을 DB에 저장하기 위해 해당 파일 명들의 리스트를 담아서 리턴합니다.

 

 

S3에 업로드 된 파일 명들이 controller에 다시 오게 됩니다.

 

이 후 해당 파일 명을 DB에 저장해주면 파일 업로드가 완료 됩니다.

 

저 과정에서 fileName을 바꿔주거나 하는 작업등을 입맛에 맞게 해주면 됩니다.

반응형