当前位置: 首页 > article >正文

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

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

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库

npm install form-data

客户端上传代码如下:

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

npm install @aws-sdk/client-s3 
npm install @aws-sdk/s3-request-presigner
npm install @aws-sdk/s3-presigned-post

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

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

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,即可获取签名的文件下载链接。


http://www.kler.cn/a/383821.html

相关文章:

  • JS数据结构之“栈”、“队列”、“链表”
  • GooglePlay: 应用和游戏的内容分级
  • CSS3_2D变换(五)
  • 训练和部署Qwen2.5,实战教程步骤,训练qwen2.5教程,vLLM,Open WebUI,LLaMA-Factory
  • 【pycharm jupyter】远程开发 启动报错
  • OpenCV视觉分析之目标跟踪(12)找到局部的最大值函数meanShift()的使用
  • 七.numpy模块
  • 2024-11-06 问AI: [AI面试题] 人工智能如何用于欺诈检测和网络安全?
  • Bert快速入门
  • 【大数据学习 | kafka高级部分】kafka的优化参数整理
  • 数据集整理
  • 机器学习:使用SVM进行人脸识别
  • Linux(CentOS)运行 jar 包
  • WireShark入门学习笔记
  • Maven(19)如何使用Maven部署项目?
  • 矩阵论 •「线性空间、基变换与向量坐标变换」
  • 批量压缩tif文件到指定物理宽度mm,同时保持DPI大于300
  • 【spring】IOC与DI
  • mysql字段是datetime如何按照小时来统计
  • Ai练习过程当中的注意事项 Ⅱ
  • 【AI日记】24.11.06 我对投资的一点浅见
  • 问:Redis为什么这么快?
  • Magentic-One:微软推出多智能体系统,用于解决跨领域的复杂网络和文件任务
  • yolov8-seg目标分割理论及代码运行实践
  • 【1个月速成Java】基于Android平台开发个人记账app学习日记——第7天,申请阿里云SMS短信服务SDK
  • 代码随想录之字符串刷题总结