aws s3 预签名上传文件,下载文件

Posted by hcy on October 11, 2021

aws s3 预签名上传文件,下载文件

需求是生成预签名下载链接,将链接发送给没有s3权限的用户,其也能正常下载而不需要登录到aws。 上传也是同理,生成预签名上传链接,用户上传时无需登录aws。

1.引入jar包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>2.17.24</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


         <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
        </dependency>

2. 下载文件,上传文件,判断文件是否存在,读取文件

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package test.util;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.internal.presigner.DefaultS3Presigner;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
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 javax.annotation.Resource;
import java.io.InputStream;
import java.time.Duration;
import java.util.Objects;

@Service
public class S3Utils {

    static S3Presigner s3Presigner;
    static S3Client s3Client;

    @Resource
    ReconFeature reconFeature;

    static {
        s3Presigner = DefaultS3Presigner
                .builder()
                .region(Region.AP_SOUTH_1)
                .credentialsProvider(InstanceProfileCredentialsProvider.create())
                .build();

        s3Client = S3Client.builder()
                .region(Region.AP_SOUTH_1)
                .credentialsProvider(InstanceProfileCredentialsProvider.create())
                .build();
    }

    /* 生成下载文件的预签名地址
     * s3Path = s3://bucket/a/b/c/
     * fileName = 123.txt
     * effectiveDay = 有效期
     */
    public static String signGetObject(String s3Path, String fileName, int effectiveDay) {
        UriComponents build = UriComponentsBuilder.fromUriString(s3Path)
                .path("/")
                .path(fileName)
                .build();
        String bucket = build.getHost();
        String key = build.getPath();
        Assert.notNull(key, "can not singFile for s3Path:" + s3Path + " fileName:" + fileName);

        if (key.startsWith("/")) {
            key = key.substring(1);
        }
        GetObjectRequest request = GetObjectRequest.builder()
                .bucket(bucket)
                .key(key)
                .build();
        PresignedGetObjectRequest presignedGetObjectRequest = s3Presigner.presignGetObject(b -> {
            b.getObjectRequest(request);
            b.signatureDuration(Duration.ofDays(effectiveDay));
        });
        return presignedGetObjectRequest.url().toString();
    }



    /* 生成上传文件的预签名地址
     * s3FullPath = s3://bucket/a/b/c/123.txt
     */
    public static String signPutObject(String s3FullPath) {
        Assert.isTrue(s3FullPath.startsWith("s3://"), "s3全路径不正确");
        UriComponents build = UriComponentsBuilder.fromUriString(s3FullPath)
                .build();
        String bucket = build.getHost();
        String key = build.getPath().substring(1);

        PutObjectRequest request = PutObjectRequest.builder()
                .bucket(bucket)
                .key(key)
                .build();
        PutObjectPresignRequest preRequest = PutObjectPresignRequest.builder()
                .signatureDuration(Duration.ofMinutes(15))
                .putObjectRequest(request)
                .build();
        PresignedPutObjectRequest presignedPutObjectRequest = s3Presigner.presignPutObject(preRequest);

        return presignedPutObjectRequest.url().toString();
    }
    
    /*
     *判断文件是否存在在s3上
     */
    public static HeadObjectResponse fileExist(String s3Path, String fileName) {
        UriComponents build = UriComponentsBuilder.fromUriString(s3Path)
                .path(fileName)
                .build();
        String key = Objects.requireNonNull(build.getPath()).substring(1);

        HeadObjectRequest req = HeadObjectRequest.builder()
                .bucket(build.getHost())
                .key(key)
                .build();
        try {
            return s3Client.headObject(req);
        } catch (NoSuchKeyException e) {
            return null;
        }
    }

    /*
     * 读取s3的文件,以文件流形式返回(注意使用完一定要关闭流,否则会导致连接池连接占用完)
     */
    public static InputStream readFile(String s3Path, String fileName) {
        UriComponents build = UriComponentsBuilder.fromUriString(s3Path)
                .path(fileName)
                .build();
        String key = Objects.requireNonNull(build.getPath()).substring(1);

        GetObjectRequest req = GetObjectRequest.builder()
                .bucket(build.getHost())
                .key(key)
                .build();
        return s3Client.getObject(req);
    }

}



转载请注明出处:https://www.huangchaoyu.com/2021/10/11/aws-s3-预签名上传文件-下载文件/