<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>aws-sdk-java</artifactId>
<version>2.14.26</version>
</dependency>
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;
import software.amazon.awssdk.utils.IoUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Duration;
@Slf4j
@RequestMapping("/loadtest")
@RestController
public class UpLoadController {
@Autowired
private AwsS3Config s3Config;
@PostMapping("/uploadFile")
public String uploadFile(@RequestPart(value = "file") MultipartFile multipartFile) {
String fileUrl = "";
try {
// 调用方法2 将MultipartFile转为File
File file = convertMultiPartToFile(multipartFile);
// 获取原文件名称
String fileName = multipartFile.getOriginalFilename();
// 使用终端节点连接到aws服务,终端节点是作为 AWS Web 服务的入口点的 URL
Region region = Region.CN_NORTHWEST_1;
String presignUrlDurationMinutes = "5000";
// 签名url有效期
long presignUrlDurationMinutesLong = Long.valueOf(presignUrlDurationMinutes);
// 文件类型 IMAGE_PNG_VALUE = "image/png"
String contentType = MediaType.IMAGE_PNG_VALUE;;
// 创建资格证书
AwsBasicCredentials awsBasicCredentials = AwsBasicCredentials.create(s3Config.getAccessKey(),s3Config.getSecretKey());
// 构建签名器
S3Presigner s3Presigner = S3Presigner.builder().region(region).credentialsProvider(StaticCredentialsProvider.create(awsBasicCredentials)).build();
// 调用方法3 获取预签署地址(要上传到的地址);参数(构建签名器、bucketName、原文件名、终端节点、keyId、AccessKey、签名有效期)
URL presignedUrl = generatePresignedUrl(s3Presigner, s3Config.getBucketName(), fileName, region, s3Config.getAccessKey(),s3Config.getSecretKey(), presignUrlDurationMinutesLong);
// 调用方法5 上传文件;参数(预签署地址、原文件名称、文件类型)
uploadObject(presignedUrl, fileName, contentType);
// 调用方法4 获取预览url;参数(签名构建器、bucketName、原文件名称)
URL url = getPresignedUrl(s3Presigner, s3Config.getBucketName(), fileName);
fileUrl = url.toString();
// 删除临时文件
file.delete();
} catch (Exception e) {
return "UploadController().uploadFile().Exception : " + e.getMessage();
}
return fileUrl;
}
// 将MultipartFile转为File
private File convertMultiPartToFile(MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
return convFile;
}
/**
* 返回预签署地址
* @param s3Presigner 构建签名器
* @param bucketName bucketName
* @param objectKey 原文件名
* @param region 终端节点
* @param accessKeyId keyId
* @param secretAccessKey AccessKey
* @param presignUrlDurationMinutesLong 签名有效期
* @return
*/
private static URL generatePresignedUrl(S3Presigner s3Presigner, String bucketName, String objectKey, Region region, String accessKeyId, String secretAccessKey, long presignUrlDurationMinutesLong) {
// 上传文件请求
PutObjectRequest putObjectRequest = PutObjectRequest.builder().bucket(bucketName).key(objectKey).build();
// 上传文件预签名请求
PutObjectPresignRequest putObjectPresignRequest = PutObjectPresignRequest.builder().signatureDuration(Duration.ofMinutes(presignUrlDurationMinutesLong)).putObjectRequest(putObjectRequest).build();
PresignedPutObjectRequest presignedPutObjectRequest = s3Presigner.presignPutObject(putObjectPresignRequest);
// 获取到预签署地址
URL presignedUrl = presignedPutObjectRequest.url();
log.info("Presigned URL: ", presignedUrl);
log.info("Method needed: ", presignedPutObjectRequest.httpRequest().method());
s3Presigner.close();
return presignedUrl;
}
/**
* 获取预签名对象:https://docs.amazonaws.cn/sdk-for-java/latest/developer-guide/examples-s3-presign.html
* 从预签名 S3 存储桶中读取内容
* @param presigner 签名构建器
* @param bucketName bucketName
* @param keyName 原文件名称
* @return 预览地址
*/
public static URL getPresignedUrl(S3Presigner presigner, String bucketName, String keyName) {
try {
// 获取对象请求;参数(bucketName、原文件名称)
GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(bucketName).key(keyName).build();
GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder().signatureDuration(Duration.ofMinutes(1000)).getObjectRequest(getObjectRequest).build();
// 预签名对象
PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(getObjectPresignRequest);
log.info("Presigned URL: ", presignedGetObjectRequest.url());
// 打开连接,获取网络对象HttpURLConnection
HttpURLConnection connection = (HttpURLConnection) presignedGetObjectRequest.url().openConnection();
// 添加请求头信息
presignedGetObjectRequest.httpRequest().headers().forEach((header, values) -> {
values.forEach(value -> {
connection.addRequestProperty(header, value);
});
});
// 发送服务需要的任何请求有效负载(当isBrowserExecutable为true时不需要)
if (presignedGetObjectRequest.signedPayload().isPresent()) {
connection.setDoOutput(true);
try (InputStream signedPayload = presignedGetObjectRequest.signedPayload().get().asInputStream();
OutputStream httpOutputStream = connection.getOutputStream()) {
IoUtils.copy(signedPayload, httpOutputStream);
}
}
// 下载执行请求的结果
try (InputStream content = connection.getInputStream()) {
log.info("Service returned response: ");
// 内容复制
IoUtils.copy(content, System.out);
}
presigner.close();
// 返回预览地址
return presignedGetObjectRequest.url();
} catch (S3Exception e) {
e.getStackTrace();
} catch (IOException e) {
e.getStackTrace();
}
return null;
}
/**
* 上传文件到亚马逊服务器
* @param presignedUrl 预签署地址
* @param objectLocalPath 原文件名称
* @param contentType 文件类型
*/
private static void uploadObject(URL presignedUrl, String objectLocalPath, String contentType) {
// 缓冲字节输出流
BufferedOutputStream bufferedOutputStream = null;
// 缓冲字节输入流
BufferedInputStream bufferedInputStream = null;
try {
// 打开连接,获取网络对象HttpURLConnection
HttpURLConnection httpURLConnection = (HttpURLConnection) presignedUrl.openConnection();
// 设置是否向HttpURLConnection输出
httpURLConnection.setDoOutput(true);
// 设置文件类型
httpURLConnection.setRequestProperty("Content-Type", contentType);
// 设置请求方式
httpURLConnection.setRequestMethod("PUT");
// 获取缓冲字节输出流
bufferedOutputStream = new BufferedOutputStream(httpURLConnection.getOutputStream());
// 传入参数本地文件路劲
bufferedInputStream = new BufferedInputStream(new FileInputStream(new File(objectLocalPath)));
byte[] buffer = new byte[1024];
// 缓冲输入流读到buffer数组
int length = bufferedInputStream.read(buffer);
while (length > 0) {
// 缓冲输出流将buffer数组中的字节写到远程服务
bufferedOutputStream.write(buffer);
length = bufferedInputStream.read(buffer);
}
// 刷新缓冲输出流,并关闭
bufferedOutputStream.flush();
bufferedOutputStream.close();
log.info("Response Code: ", httpURLConnection.getResponseCode());
log.info("Response Message: ", httpURLConnection.getResponseMessage());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedOutputStream != null) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedInputStream != null) {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}