AWS S3上传文件

1 篇文章 0 订阅

原因:

最近项目需要对接AWS平台,上传文件到AWS S3,按照官方文档对接,经历不少波折,所幸,最终完成了业务要求,成功对接AWS S3,防止以后忘记,特此记录一下

前提

对接AWS S3,需要满足一下前提条件

1、在AWS开通S3并且创建存储桶【bucket】

如果想让你的文件能够公共读,需要设置“权限-》屏蔽公共访问权限-》阻止所有公开访问:关闭”

2、提前准备IAM子用户以及相关权限策略
2.1 创建上传文件权限策略

示例:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
2.2 创建获取STS Token的权限

备注:如果不需要使用STS Token,请跳过此步骤
示例:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sts:GetAccessKeyInfo",
                "sts:GetSessionToken",
                "sts:AssumeRole"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

备注:【示例只提供了上传文件和获取STS Token的权限,如果需要更多权限,请按照官方文档增加】

2.2 创建IAM用户和访问密钥

创建一个IAM子用户,将2.1创建的策略授权给IAM子用户;
创建成功后,再创建一个访问密钥,记得在创建成功保存,如果不保存,在其他地方无法获取

按照SDK开发:上传文件和获取STS Token

本文示例,使用java语言,springboot开发

1、导入jar
	<!-- AWS S3 文件上传必须的jar -->
	  <dependency>
		  <groupId>com.amazonaws</groupId>
		  <artifactId>aws-java-sdk-s3</artifactId>
	  </dependency>
	  <!-- 提供给客户端临时访问凭据,STS Token -->
	  <dependency>
		  <groupId>software.amazon.awssdk</groupId>
		  <artifactId>sts</artifactId>
	  </dependency>
<dependencyManagement>
    <dependencies>
   	 	<!-- 设置统一的版本,防止手动设置版本导致的兼容和冲突问题 -->
		<dependency>
			<groupId>software.amazon.awssdk</groupId>
			<artifactId>bom</artifactId>
			<version>2.21.20</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
    </dependencies>
</dependencyManagement>
	<build>
		<plugins>
		<!-- 设置maven的版本,AWS SDK V2版本,要求maven版本大于3.0.0-->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.22.1</version>
				<configuration>
					<groups>IntegrationTest</groups>
				</configuration>
			</plugin>
		</plugins>
	</build>
	
	 <repositories>
	 		<!-- maven 3.6.1以后的版本,不支持HTTP仓库地址,需要手动指定信任的仓库地址-->
		 <repository>
			 <id>spring-snapshots</id>
			 <url>http://repo.spring.io/libs-snapshot</url>
		 </repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<url>http://repo.spring.io/libs-snapshot</url>
		</pluginRepository>
	</pluginRepositories>
2、配置文件
#aws-s3
aws.s3.status=true
aws.s3.accessKey=
aws.s3.secretKey=
aws.s3.bucketName=
aws.s3.region=us-east-1
aws.s3.uploadPath=
aws.s3.viewPath=https://{s3实例Id}.amazonaws.com/
aws.s3.fileRoot=xxxx/xxx
#获取STS Token的配置
aws.sts.roleArn=arn:aws:iam::{iamId}:role/{roleName}
aws.sts.roleSessionName={roleSessionName}
3、上传文件工具类

为了使用移植方便,直接使用静态组件

package com.test.common.cloudPlatform.aws.s3;

import com.aliyun.oss.OSSException;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CopyObjectResult;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
import software.amazon.awssdk.services.sts.model.AssumeRoleResponse;
import software.amazon.awssdk.services.sts.model.Credentials;
import software.amazon.awssdk.services.sts.model.StsException;

import javax.annotation.PostConstruct;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.*;


@Component
public class AWSS3Util {
    
    private Logger logger = LoggerFactory.getLogger(AWSS3Util.class);
    
	public static final String HTMLHEAD = "<!DOCTYPE html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no'/><title>FitTrack</title><style rel='stylesheet' type='text/css'> body{margin: 16px;} img{max-width:100%;margin:auto;}</style></head><body>";

	public static final String HTMLFOOT = "</body></html>";

	@Value("${aws.s3.accessKey}")
	private String accessKeyT;
	private static String accessKey;


	@Value("${aws.s3.secretKey}")
	private String secretKeyT;
	private static String secretKey;


	@Value("${aws.s3.bucketName}")
	private String bucketNameT;
	private static String bucketName;


	@Value("${aws.s3.region}")
	private String regionT;
	private static String region;


	@Value("${aws.s3.uploadPath}")
	private  String uploadPathT;
	private static String uploadPath;

	@Value("${aws.s3.viewPath}")
	private  String viewPathT;
	private static String viewPath;

	@Value("${aws.s3.fileRoot}")
	private String fileRootT;
	private static String fileRoot;

	@Value("${aws.sts.roleArn}")
	private String roleArnT;
	private static String roleArn;

	@Value("${aws.sts.roleSessionName}")
	private String roleSessionNameT;
	private static String roleSessionName;

	/**
	 * 初始化方法,使用@PostConstruct注解能够在对象通过@Component初始化后调用该方法
	 * ,将通过@Value加载的值赋值给静态变量
	 */
	@PostConstruct
	private void init(){
		accessKey = accessKeyT;
		secretKey = secretKeyT;
		bucketName = bucketNameT;
		region = regionT;
		uploadPath = uploadPathT;
		viewPath = viewPathT;
		fileRoot = fileRootT;
		roleArn = roleArnT;
		roleSessionName = roleSessionNameT;
	}
   
    /**
	 * 上传base64图片文件
	 * @param queryRequest 文件
 	 * @return
	 */
	public static String upLoadBase64Image(ImageRequest queryRequest) {
		MultipartFile file = BASE64DecodedMultipartFile.base64ToMultipart(queryRequest.getImgBase64());
		BasicAWSCredentials cred = new BasicAWSCredentials(accessKey, secretKey);
		AmazonS3 amazonS3 = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(cred))
				.withRegion(region)
				.build();

		String filePath =  uploadPath + getFilename(queryRequest.getImgPath(), "",queryRequest.getAutoImgFilePath());
		if(queryRequest.getAutoPathStatus() != null && queryRequest.getAutoPathStatus() == 1){
			filePath = queryRequest.getImgPath();
		}
		// 设置上传文件大小
		ObjectMetadata meta = new ObjectMetadata();
		meta.setContentLength(file.getSize());
		meta.setContentType("image/png");
		if(!StringSelfUtil.isEmpty(queryRequest.getImgConfig())){
			//防止中文乱码,进行base64编码
			String imgConfig = Base64.getEncoder().encodeToString(queryRequest.getImgConfig().getBytes());
			meta.setHeader("x-amz-meta-config",imgConfig);
		}
		// 上传文件
		try {
			amazonS3.putObject(bucketName, filePath, file.getInputStream(), meta);
		}  catch (Exception e) {
			e.printStackTrace();
		} finally {
//			amazonS3.shutdown();
		}
		return viewPath+filePath;
	}
	
	public static String saveHtml(String htmlText) {
		String filePath =getFilename(UUID.randomUUID().toString()+".html", "",0);
		htmlText = HTMLHEAD +htmlText+HTMLFOOT;
		BasicAWSCredentials cred = new BasicAWSCredentials(accessKey, secretKey);
		AmazonS3 client = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(cred))
				.withRegion(region)
				.build();
		// 设置上传文件大小
		ObjectMetadata meta = new ObjectMetadata();
		meta.setContentType("text/html;charset=UTF-8");
		// 保存html文件
		try {
			client.putObject(bucketName, filePath,new ByteArrayInputStream(htmlText.getBytes()),meta);
		}catch (Exception e){

		}finally {
//			client.shutdown();
		}
		return viewPath+filePath;
	}
	
    
 // 生成文件名加目录
    public static String getFilename(String dir,String suffix,Integer autoImgFilePath){
       	// 使用uuid生成唯一文件名
        String cuurDdate = DateUtils.format(DateUtils.currentDate(), DateUtils.DATE_FORMAT_PATTERN);
        String fileRootTemp = "";
		//使用自定义地址
		if(autoImgFilePath != null && autoImgFilePath == 1){
			fileRootTemp = fileRoot;
		}else{
			fileRootTemp = fileRoot+"/"+cuurDdate;
		}
        if(StringSelfUtil.isEmpty(suffix)){
        	return fileRootTemp+"/"+dir;
        }else{
        	return fileRootTemp+"/"+dir+"."+suffix;
        }
    }

	public static Map getStsToken( ) {
		final String usage = "";
//		Region region = Region.US_EAST_1;
		System.setProperty("aws.accessKeyId",accessKey);
		System.setProperty("aws.secretAccessKey",secretKey);
		StsClient stsClient = StsClient.builder()
				.region(Region.of(region))
				.build();
		try {
			AssumeRoleRequest roleRequest = AssumeRoleRequest.builder()
					.roleArn(roleArn)
					.roleSessionName(roleSessionName)
					.build();
			AssumeRoleResponse roleResponse = stsClient.assumeRole(roleRequest);
			Credentials myCreds = roleResponse.credentials();

			// Convert the Instant to readable date.
			DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
					.withLocale(Locale.US)
					.withZone(ZoneId.systemDefault());
			Map<String,Object> result = new HashMap<>();
			result.put("accessKeyId",myCreds.accessKeyId());
			result.put("accessKeySecret",myCreds.secretAccessKey());
			result.put("stsToken",myCreds.sessionToken());
			result.put("expiration",formatter.format(myCreds.expiration()));
			result.put("region",region);
			result.put("bucket",bucketName);

			return  result ;
		} catch (StsException e) {
			System.err.println(e.getMessage());
		}
		stsClient.close();
		return null;
	}

	/**
	 * 拷贝文件
	 * @param sourceObjectName
	 */

	public static void copyObject(String sourceObjectName,String destinationObjectName) {
		BasicAWSCredentials cred = new BasicAWSCredentials(accessKey, secretKey);
		AmazonS3 client = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(cred))
				.withRegion(region)
				.build();

		sourceObjectName = fileRoot+sourceObjectName;
		destinationObjectName = fileRoot+destinationObjectName;

		// 拷贝文件。
		CopyObjectResult result = client.copyObject(bucketName, sourceObjectName, bucketName, destinationObjectName);
		//System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());

		// 关闭OSSClient。
//		client.shutdown();

	}

	/**
	 * 上传文本内容
	 * @param filePath
	 * @return
	 */

	public static String saveTxtToFile(String filePath,String text) {
		filePath = fileRoot+filePath;
		BasicAWSCredentials cred = new BasicAWSCredentials(accessKey, secretKey);
		AmazonS3 client = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(cred))
				.withRegion(region)
				.build();
		try {
			// 设置文件Content-Type
			String suffix = filePath.substring(filePath.lastIndexOf(".")+1,filePath.length());
			if(suffix!=null){
				ObjectMetadata meta = new ObjectMetadata();
				meta.setContentType("text/plain");
				// 保存js文件
				if(suffix.equals("js")){
					meta.setContentType("application/javascript");
				}
				if(suffix.equals("css")){
					meta.setContentType("text/css");
				}
				client.putObject(bucketName, filePath,new ByteArrayInputStream(filePath.getBytes()),meta);
			}else{
				client.putObject(bucketName, filePath,text);
			}
		} catch (OSSException e) {
			e.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		} finally {
//			client.shutdown();
		}
		return viewPath+filePath;
	}
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值