AWS S3在客户端应用不能使用aws-sdk场景下的文件上传与下载

简介

通常情况下,应用程序上传文件到AWS S3,会使用aws-sdk,但是有些情况下,客户端应用会有安装限制,比如不能安装aws-sdk,此时我们就需要通过其他方式实现文件上传与下载。

这里我们提供一个服务端,在服务端安装aws-sdk。对于文件上传,服务端通过aws-sdk生成一个upload policy,然后将这个upload policy返回给客户端,客户端通过这个upload policy上传文件。对于文件下载,服务端通过aws-sdk生成一个presigned url,然后将这个presigned url返回给客户端,客户端通过这个presigned url下载文件。

文件上传

服务端安装aws-sdk

shell 复制代码
npm install @aws-sdk/client-s3 
npm install @aws-sdk/s3-request-presigner
npm install @aws-sdk/s3-presigned-post

服务端生成upload policy

在服务端的 controller 里添加一个路由产生并返回 upload policy

typescript 复制代码
import { S3Client } from "@aws-sdk/client-s3";
import { createPresignedPost } from '@aws-sdk/s3-presigned-post';
import { Conditions } from "@aws-sdk/s3-presigned-post/dist-types/types";

...

app.get("/s3/getUploadPolicy", async (req: Request, res: Response) => {
    const bucket = req.query.bucket?.toString();
    const key = req.query.key?.toString();
    const id = req.query.id?.toString();
    if (bucket && key) {
        const fields = {'x-amz-meta-uuid': '' + id};
        const conditions: Conditions[] = [
            ['starts-with', '$key', key],
            ['content-length-range', 16, 10 * 1024 * 1024],
            ['starts-with', '$Content-Type', '']
        ];

        const params = {
            Bucket: bucket,
            Key: key,
            Conditions: conditions,
            Fields: fields,
            Expires: 10 * 60 * 60,
        };
        const client = new S3Client();
        const policy = await createPresignedPost(client, params);
        res.json({ policy: policy });
    } else {
        res.json({ error: 'error' });
    }
});

客户端上传文件

客户端上传需要使用form-data库做表单提交,因此需要先安装form-data库

shee 复制代码
npm install form-data

客户端上传代码如下:

typescript 复制代码
import * as FormData from 'form-data';
import { createReadStream } from "fs";

async function testForUpload(bucket: string, key: string, id: string, file: string) {
    // http://localhost:3000/s3/getUploadPolicy?bucket=mybucket&key=abc.tar.gz&uuid=12345
    const url = `http://localhost:3000/s3/getUploadPolicy?bucket=${bucket}&key=${key}&uuid=${id}`;
    const response = await fetch(url);
    const policy = await response.json();
    console.log(policy);

    const form = new FormData();
    form.append('key', policy.fields.key);
    form.append('Content-Type', 'application/gzip');
    form.append('X-Amz-Credential', policy.fields['X-Amz-Credential']);
    form.append('X-Amz-Algorithm', policy.fields['X-Amz-Algorithm']);
    form.append('X-Amz-Date', policy.fields['X-Amz-Date']);
    form.append('Policy', policy.fields.Policy);
    form.append('X-Amz-Signature', policy.fields['X-Amz-Signature']);
    form.append('x-amz-meta-uuid', policy.fields['x-amz-meta-uuid']);

    form.append('file', createReadStream(file));
    await form.submit(policy.url);
}
// testForUpload('mybucket', 'abc.tar.gz', '12345', '/Volumes/mydisk/test/abc.tar.gz');
  • 客户端代码首先调用服务端接口获取upload policy,请求的时候传递bucket、key和id,服务端会根据这些参数生成upload policy;
  • 然后客户端使用form-data库生成一个form,将参数、policy和文件添加到form中,然后将form提交到服务端返回的url;

文件下载

服务端安装aws-sdk

shell 复制代码
npm install @aws-sdk/client-s3 
npm install @aws-sdk/s3-request-presigner
npm install @aws-sdk/s3-presigned-post

服务端生成签名的文件下载链接

在服务端的 controller 里添加一个路由产生并返回签名的文件访问url

typescript 复制代码
import {
    S3Client,
    GetObjectCommand,
} from "@aws-sdk/client-s3";
import {getSignedUrl} from '@aws-sdk/s3-request-presigner';

...

app.get("/s3/getDownloadUrl", async (req: Request, res: Response) => {
    const bucket = req.query.bucket?.toString();
    const key = req.query.key?.toString();
    if (bucket && key) {
        const client = new S3Client();
        const url = await getSignedUrl(
            client,
            new GetObjectCommand({
                Bucket: bucket,
                Key: key,
            }),
            {
                expiresIn: 10 * 60 * 60,
            }
        );
        res.json({ url: url });
    } else {
        res.json({ error: 'error' });
    }
});

然后客户端请求此链接,并添加bucket和key参数,比如http://localhost:3000/s3/getDownloadUrl?bucket=mybucket\&key=abc.tar.gz,即可获取签名的文件下载链接。

相关推荐
无责任此方_修行中1 天前
从 HTTP 轮询到 MQTT:我们在 AWS IoT Core 上的架构演进与实战复盘
后端·架构·aws
weixin_307779134 天前
AWS Lambda解压缩S3 ZIP文件流程
python·算法·云计算·aws
在云上(oncloudai)7 天前
AWS KMS VS AWS Cloud HSM VS AWS Secret Manager?
云计算·aws
大斯斯7 天前
AWS 亚马逊云预警通知接入钉钉告警(微信同样适用)
aws
大斯斯7 天前
AWS 通过 CloudWatch 实现应用日志告警
aws
指剑11 天前
借助Rclone快速从阿里云OSS迁移到AWS S3
阿里云·云计算·迁移学习·aws·亚马逊云科技·rclone
huainian11 天前
AWS 云小白学习指南 (一)
云计算·aws
xybDIY11 天前
智能云探索:基于Amazon Bedrock与MCP Server的AWS资源AI运维实践
运维·人工智能·aws
(:满天星:)12 天前
AWS EKS节点扩容时NLB与Ingress的故障处理与优化方案
云计算·aws