关于AWS S3
AWS S3是指Amazon Web Services提供的一种对象存储服务,允许用户在云中存储和检索任意数量的数据对象。
从通俗的角度来说,我们可以理解为这是一个七牛云服务,只是国际版的而已。
也跟阿里云的存储服务差不多,只是一般的外企会选择使用AWS的服务,所以外企的同学会比较熟悉AWS。
AWS S3的基本组成包括Bucket、Object与Key。
当我们创建一个项目的时候,我们会在S3服务中创建一个Bucket,作为存放我们数据的容器。而当我们需要上传对象的时候,我们所上传的文件,我们会赋予一个名字,这个就是我们所说的Key,而Object指的就是我们所要上传的那个文件。
文件上传流程
在进行代码开发之前,我们需要了解下上传的整个流程,并与直接上传到服务器的方式做对比。
当我们没有使用第三方的存储服务的时候,我们会选择自己写一个上传的接口,并将数据存储在服务器上,但是当上传大数据的时候,我们就有可能出现卡顿的问题,毕竟很难保证自己的服务器带宽还有存储足够。
因此,当我们使用第三方存储服务的时候,我们并不会在存储数据的时候使用后台的接口,而是使用后端生成上传/读取文件链接的方式,并将文件链接发给前端,让前端自己去上传文件。
这种方式生成的链接,便称之为预签名链接。
当前端拿到预签名链接的时候,就可以直接用上传文件了。
生成预签名
在生成预签名链接之前,我们需要准备几个参数。
第一个是我们的密钥以及id,一般都是由管理员生成给我们,所以不需要太关心怎么去获取。
第二个参数为regoin,也就是我们的bucket所存的地区,地区可以在我们的aws网站中看到。
如上图,Bucket所在地区是新加坡,所以我们的地址为ap-southeast-1
当拥有了上述的三个参数之后,我们需要在我们的代码中初始化一个s3服务的实例,需要注意的是,此处用的是v3的版本。
"@aws-sdk/client-s3": "^3.427.0"
当我们在后端中确定了版本之后,我们就需要设置一个s3的实例了。
this.s3 = new S3Client({ credentials: { accessKeyId: key, secretAccessKey: secret }, region });
上述的参数中,在前面已经说过了,三个参数都是必要的。
与对Db的操作相同,我们的后续,都会在这个示例中进行操作。
当我们创建好一个实例之后,我们需要直接调用getSignedUrlFromS3方法去直接生成预签名链接。
https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/example_s3_Scenario_PresignedUrl_section.html
async getSignedUrlForUpload(fileName: string, folder?: string): Promise<string> { // If the folder does not exist, S3 will automatically create the folder const putObjectCommand = new PutObjectCommand({ Bucket: bucket, Key: (folder ? folder + '/' : '') + fileName }); return await getSignedUrlFromS3(this.s3, putObjectCommand, { expiresIn: ONE_HOUR }); }
以上代码中,生成预签名链接的方式是我们先调用PutObjectCommand的方式在我们构建好的Bucket中生成我们的Key,准备上传文件的"容器"
接下来,我们直接调用s3的getSignedUrlFromS3方法,去获取到一个该"容器"的预签名地址,并且设置过期时间,于是一个预签名链接就生成了,可以准备给前端了。
前端如何上传?这个问题问得好,我建议直接用你喜欢的方式上传…
await axios.put(url, file, { headers: { 'Content-Type': 'multipart/form-data' }, // Only show progress bar in non-test environment because it will cause test to fail due to this issue https://github.com/axios/axios/issues/5984 ...(EnvConfigs.nodeEnv !== 'test' ? { onUploadProgress: progressEvent => { setFileInfo({ fileName: file.name, fileUrl: '', fileSize: getReadableFileSize(file.size), status: UploadStatus.InProgress, progress: Math.round((progressEvent.loaded * 100) / (progressEvent.total || file.size)) }); } } : {}) });
最后,在我们的s3服务上,可以成功的看到文件已经上传了。
原创不易~ 求关注~ 希望能帮到你~