써먹는 웹개발
[Spring Boot/IntelliJ] aws s3와 연동하여 파일 업로드/다운로드 구현 - 2편. 업로드/다운로드 기능 구현 본문
[Spring Boot/IntelliJ] aws s3와 연동하여 파일 업로드/다운로드 구현 - 2편. 업로드/다운로드 기능 구현
kmhan 2021. 5. 2. 10:291편. 환경설정 : kmhan.tistory.com/504
1. jsp 호출
1) pom.xml에서 dependency에 aws등 필요한 기능 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.901</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
|
cs |
※ pom.xml 파일 우클릭 Maven > Reload project를 해야 aws를 import할때 에러가 나지 않는다.
ex) import com.amazonaws.auth.AWSCredentials;
2) application.properties에서 jsp를 호출하기 위한 경로를 입력
...prefix : 폴더경로
...suffix : 확장자
3) Run을 실행하기 위한 콘트롤러 작성
파일명 : SpringS3AmazonApplication.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package com.example.awsfileupload;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringS3AmazonApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(SpringS3AmazonApplication.class, args);
}
public void run(String... args) throws Exception {
}
}
|
cs |
org.springframework.boot.CommandLineRunner;</div><div
4) index.jsp 파일 생성
경로 : webapp/WEB-INF/views/index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>파일 업로드/다운로드</title>
</head>
<body>
<h1>파일 업로드/다운로드</h1> <hr>
<form id="fileFrm">
파일 : <input type="file" name="file" onchange="$('#fileList *').remove()" size="35">
<button type="button" onclick="fileUpload()">업로드</button>
</form>
<div id="fileList"></div>
</body>
</html>
|
cs |
2. S3환경을 사용할 수 있도록 자바 소스에 추가
1) application.properties에 aws 사이트에서 생성한 버킷을 참고하여 필요한 내용 작성
1-1) access_key_id : 액세스 키 ID
1-2) secret_access_key : 보안 액세스 키
※ 찾는 방법
- 종 모양 오른쪽에 아이디를 클릭한뒤 내 보안 자격 증명 클릭
- 보안 자격 증명 > 엑세스 키 > 새 액세스 키 만들기를 하면 액세스 키 ID와 보안 액세스 키가 나옵니다.
※ 이 2가지는 절대로 외부에 공유하면 안되며 공유시 막대한 호스트비를 내게 될 수 있습니다.
1-3) bucket : (생성한) 버킷 명
1-4) region : AWS 리전 (나라 및 지역)
2) a3client 함수생성 (파일명 : S3Config.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
package com.example.awsfileupload.config;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
@Configuration
public class S3Config {
@Value("${jsa.aws.access_key_id}")
private String awsId;
@Value("${jsa.aws.secret_access_key}")
private String awsKey;
@Value("${jsa.s3.region}")
private String region;
@Bean
public BasicAWSCredentials basicAWSCredentials() {
return new BasicAWSCredentials(awsId, awsKey);
}
@Bean
public AWSCredentialsProvider awsCredentialProvider(AWSCredentials awsCredentials) {
return new AWSCredentialsProvider() {
@Override
public AWSCredentials getCredentials() { return awsCredentials; }
@Override
public void refresh() {}
};
}
@Bean
public AmazonS3 s3client() {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(awsId, awsKey);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(Regions.fromName(region))
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
return s3Client;
}
}
|
cs |
2. 파일 업로드
1) java 소스 (파일명 : FileUploadDownloadController.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
package com.example.awsfileupload;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3URI;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.util.IOUtils;
import org.apache.logging.log4j.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.*;
@RestController
public class FileUploadDownloadController {
private Logger logger = LoggerFactory.getLogger(FileUploadDownloadController.class);
@Autowired
private AmazonS3 s3client;
@Value("${jsa.s3.bucket}")
private String bucketName;
@Value("${jsa.s3.region}")
private String region;
public File convert(MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
return convFile;
}
// 파일 업로드 요청
@PostMapping("/upload")
public String uploadSingle(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request) throws Exception {
try {
String fName = multipartFile.getOriginalFilename();
System.out.println(fName.indexOf("."));
if (fName.indexOf(".") != -1) {
String ext = fName.split("\\.")[1];
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, UUID.randomUUID() + "." + ext, convert(multipartFile));
putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
s3client.putObject(putObjectRequest);
logger.info("===================== Upload File - Done! =====================");
}
} catch (AmazonServiceException ase) {
logger.info("Caught an AmazonServiceException from PUT requests, rejected reasons:");
logger.info("Error Message: " + ase.getMessage());
logger.info("HTTP Status Code: " + ase.getStatusCode());
logger.info("AWS Error Code: " + ase.getErrorCode());
logger.info("Error Type: " + ase.getErrorType());
logger.info("Request ID: " + ase.getRequestId());
} catch (AmazonClientException ace) {
logger.info("Caught an AmazonClientException: ");
logger.info("Error Message: " + ace.getMessage());
}
return "success";
}
}
|
cs |
2) jsp에 javascript 소스 (파일명 : index.jsp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<%@ page import="java.util.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
var fileListTag = "";
function fileUpload(){
$.ajax({
type: "POST",
enctype:"multipart/form-data",
url:"/upload",
data: new FormData($("#fileFrm")[0]),
processData:false,
contentType:false,
success: function(data) {
// 파일 다운로드 기능 추가예정 }
});
}
</script>
<!DOCTYPE html>
|
cs |
3. 파일 다운로드
1) java 소스에 다음 메소드 추가 (파일명 : FileUploadDownloadController.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 파일 다운로드 목록 불러오기
@RequestMapping(value = "/downloadList", method = RequestMethod.GET)
public String fileDownloadList(HttpServletRequest request, HttpServletResponse response) throws IOException {
ObjectListing objectListing = s3client.listObjects(bucketName); //prefix가 필요하지 않은 경우 다음과 같이 사용할 수도 있다. => ObjectListing objectListing = s3Client.listObjects(BucketName);
List<String> arrayKeyList = new ArrayList<>();
List<Date> arrayModTimeList = new ArrayList<>();
for (S3ObjectSummary s : objectListing.getObjectSummaries()) {
arrayKeyList.add(s.getKey());
arrayModTimeList.add(s.getLastModified());
}
Date max = Collections.max(arrayModTimeList);
String fileName = arrayKeyList.get(arrayModTimeList.indexOf(max));
String url = "https://" + bucketName + ".s3." + region + ".amazonaws.com/" + fileName;
return url;
}
|
cs |
2) jsp에 javascript 소스 (파일명 : index.jsp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<%@ page import="java.util.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
var fileListTag = "";
function fileUpload(){
$.ajax({
type: "POST",
enctype:"multipart/form-data",
url:"/upload",
data: new FormData($("#fileFrm")[0]),
processData:false,
contentType:false,
success: function(data) {
$.ajax({
url: "/downloadList",
type:"GET",
success:function(data){
if(data != undefined || data != null) {
$("#fileList *").remove();
fileListTag = "<a href=\""+data+"\">"+data+"</a>";
$("#fileList").append(fileListTag);
}
}
});
}
});
}
</script>
<!DOCTYPE html>
|
cs |
3) 생성된 링크 클릭시 파일을 바로 열지않고 다운로드하고 싶을때 주의사항
- FileUploadDownloadController.java > uploadSingle 메서드에 다음 소스 추가
1
2
3
|
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType("plain/text");
putObjectRequest.setMetadata(metadata);
|
cs |
※ 파일 다운로드 링크 클릭시 에러 페이지가 뜬다면 2가지를 다시 확인할 것
1) ACL > 모든 사람에 객체는 '나열', 버킷 ACL에는 '읽기'로 되어있는지 확인
2) 업로드 기능 구현한 자바 파일에 해당 소스가 작성되어있는지 확인
1
|
putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
|
cs |
도움이 되셨나면 하트와 댓글 남겨주세요.
'Server > Spring' 카테고리의 다른 글
[Spring] Maven 환경에서 index.jsp 호출 방법 (0) | 2021.05.07 |
---|---|
[Spring] 처음받은 프로젝트의 로컬 주소를 찾을 수 없을때 (0) | 2021.05.04 |
[Spring] 자주쓰는 @annotaion 목록 (0) | 2021.03.22 |
[Spring] 의존주입 (DI) (0) | 2020.05.11 |
[Spring] spring boot와 spring framework의 차이(장단점) (0) | 2020.05.02 |