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

Amazon S3 对象存储服务深度解析:存储原理、应用场景与实战指南

Amazon S3 对象存储服务深度解析:存储原理、应用场景与实战指南

Amazon S3对象存储服务,在可扩展性、数据可用性、安全性和能效方面业界领先,数百万不同规模和行业的客户可以为几乎任何应用场景存储、管理、分析和保护任意数量的数据,例如数据湖、云原生应用程序和移动应用程序,借助高成本效益的存储类和易于使用的管理功能,可以优化成本、组织并分析数据,以及配置精细调整过的访问控制,从而满足特定的业务和合规性要求。

亚马逊云科技注册

亚马逊云科技提供众多免费云产品,其中Amazon EC2 云服务器可以免费体验,访问亚马逊云科技官网

1、亚马逊云科技官网账号注册

在这里插入图片描述

2、进入注册页面(使用电子邮件地址进行注册)

  • 进入 创建亚马逊云科技账户页面(如果最近登录过 亚马逊云科技,请选择登录控制台。如果未显示创建新亚马逊云科技账户,请首先选择登录其他账户,然后选择创建新亚马逊云科技账户)

  • 根用户电子邮件地址 中,输入电子邮件地址,编辑亚马逊云科技账户名称,然后选择验证电子邮件地址,该地址会收到一封包含验证码的亚马逊云科技验证电子邮件

在这里插入图片描述

  • 安全验证

在这里插入图片描述

  • 验证电子邮件地址(输入收到的代码,然后选择验证,可能需要几分钟才会收到代码,检查电子邮件和垃圾邮件文件夹中是否有验证码电子邮件)

在这里插入图片描述

3、设置用户信息

  • 创建密码:输入根用户密码和确认根用户密码,然后选择继续
  • 添加您的联系信息:选择个人或企业(个人账户和企业账户具有相同的特性和功能)

在这里插入图片描述

4、添加付款信息( 账单信息页面上,输入付款方式的信息,然后选择验证并添加,必须先添加有效的支付方式才能继续注册)

在这里插入图片描述

5、用户信息验证(选择接收验证码的联系方式、选择电话号码的国家或地区代码)

在这里插入图片描述

6、客户验证与激活账户(选择亚马逊云科技支持服务计划)

在这里插入图片描述

7、完成注册

在这里插入图片描述

Amazon S3工作原理

在这里插入图片描述

Amazon S3 将数据作为对象存储在存储桶中。对象是一个文件和描述该文件的任何元数据。存储桶是对象的容器。要将数据存储在 Amazon S3 中,需要先创建一个存储桶并指定存储桶名称和亚马逊云科技区域。然后,将数据作为 Amazon S3 中的对象上传到该存储桶。每个对象都有一个密钥(或密钥名称),它是存储桶中对象的唯一标识符。

S3 提供可供您配置以支持您的特定应用场景的功能。例如,您可以使用 S3 版本控制将对象的多个版本保留在同一个存储桶中,这样就可以恢复意外删除或覆盖的对象。存储桶及其中的对象是私有的,只能在明确授予访问权限的情况下进行访问。您可以使用存储桶策略、Amazon Identity and Access Management(IAM)策略、S3 接入点和访问控制列表(ACL)来管理访问权限。

Amazon S3创建流程

1、Amazon S3创建前提是拥有一个亚马逊云科技账号即可领取Amazon S3服务免费体验

2、首页找到 Amazon S3 服务选项

在这里插入图片描述

3、创建存储桶

在这里插入图片描述

4、存储桶的常规配置

  • 桶名称
  • 区域
  • 对象所有权
  • 加密设置
  • 高级配置

在这里插入图片描述

5、加密类型、存储桶密钥

在这里插入图片描述

6、等待存储桶创建成功即可

在这里插入图片描述

7、存储桶配置

在这里插入图片描述

8、定义新文件夹的名称,根据需求进行相应配置

在这里插入图片描述

9、创建成功即可在Amazon S3存储桶中存储和同步数据了

在这里插入图片描述

Amazon S3实现网盘文件上传下载功能

基于 Vue.js + Spring Boot + Amazon S3 的网盘系统实现,包含文件上传、下载、列表展示、文件夹管理等

后端实现(Spring Boot + Amazon SDK)
  • application.properties配置

如下application.properties信息需要根据自己的Amazon S3配置信息替换

#AmazonS3配置
aws.access-key=key-id          #AmazonS3密钥ID
aws.secret-key=key      #AmazonS3访问密钥
aws.region=region                     #存储桶区域
aws.s3.bucket-name=bucket-name         #存储桶名称#文件上传配置
spring.servlet.multipart.max-file-size=50MB    # 单个文件最大大小
spring.servlet.multipart.max-request-size=50MB # 单次请求最大大小#应用配置
spring.application.name=s3-cloud-storage       # 应用名称
server.port=8080                               # 服务器端口
  • S3Config.java

通过 @Configuration 注解标记为配置组件,使用 @Value 从配置文件注入亚马逊云科技凭证、区域和存储桶名称,并通过 @Bean 注解创建两个核心组件:S3Client 用于与 S3 服务交互,采用静态凭证提供器注入凭证;bucketName 作为字符串 Bean 提供存储桶名称,便于在其他组件中注入使用,实现了与 S3 服务的基础连接配置

package com.example.s3cloud.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;@Configuration
public class S3Config {@Value("${aws.access-key}")private String accessKey;@Value("${aws.secret-key}")private String secretKey;@Value("${aws.region}")private String region;@Value("${aws.s3.bucket-name}")private String bucketName;@Beanpublic S3Client s3Client() {return S3Client.builder().region(Region.of(region)).credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))).build();}@Beanpublic String bucketName() {return bucketName;}
}
  • S3Service.java

通过 Spring 管理,生成唯一文件键确保路径不冲突,设 ACL=PRIVATE 保证文件私有,伪目录机制模拟文件夹结构,通过预签名 URL 实现安全临时访问,所有操作均自动处理签名和加密传输

package com.example.s3cloud.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;import java.io.IOException;
import java.net.URL;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;@Service
public class S3Service {private final S3Client s3Client;private final String bucketName;@Autowiredpublic S3Service(S3Client s3Client, String bucketName) {this.s3Client = s3Client;this.bucketName = bucketName;}// 上传文件到S3public String uploadFile(String userId, String folderPath, MultipartFile file) throws IOException {String fileKey = generateFileKey(userId, folderPath, file.getOriginalFilename());PutObjectRequest request = PutObjectRequest.builder().bucket(bucketName).key(fileKey).contentType(file.getContentType()).acl(ObjectCannedACL.PRIVATE).build();s3Client.putObject(request, RequestBody.fromInputStream(file.getInputStream(), file.getSize()));return fileKey;}// 生成预签名下载URLpublic String generatePresignedUrl(String fileKey, Duration expiration) {GetObjectRequest request = GetObjectRequest.builder().bucket(bucketName).key(fileKey).build();return s3Client.utilities().generatePresignedUrl(request, expiration).toString();}// 列出文件夹内容public List<S3Object> listFolderContent(String prefix) {ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(bucketName).prefix(prefix).delimiter("/").build();ListObjectsV2Response response = s3Client.listObjectsV2(request);return new ArrayList<>(response.contents());}// 创建文件夹(S3中通过上传零字节文件实现)public void createFolder(String folderKey) {PutObjectRequest request = PutObjectRequest.builder().bucket(bucketName).key(folderKey + "/").build();s3Client.putObject(request, RequestBody.empty());}// 删除文件或文件夹public void delete(String key) {DeleteObjectRequest request = DeleteObjectRequest.builder().bucket(bucketName).key(key).build();s3Client.deleteObject(request);}// 生成唯一文件键private String generateFileKey(String userId, String folderPath, String originalFilename) {String uuid = UUID.randomUUID().toString();return String.format("user/%s/%s/%s-%s", userId, folderPath, uuid, originalFilename);}
}
  • FileController.java

提供文件上传、列表查询、生成下载链接和删除接口,依赖 S3Service 实现业务逻辑,接口基于用户 ID 和路径操作 S3,返回统一格式响应并处理异常

package com.example.s3cloud.controller;import com.example.s3cloud.model.FileInfo;
import com.example.s3cloud.model.ResponseResult;
import com.example.s3cloud.service.S3Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.services.s3.model.S3Object;import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;@RestController
@RequestMapping("/api/files")
public class FileController {@Autowiredprivate S3Service s3Service;// 上传文件@PostMapping("/upload")public ResponseResult<String> uploadFile(@RequestParam("userId") String userId,@RequestParam("folderPath") String folderPath,@RequestParam("file") MultipartFile file) {try {String fileKey = s3Service.uploadFile(userId, folderPath, file);return ResponseResult.success(fileKey);} catch (Exception e) {return ResponseResult.error("上传失败: " + e.getMessage());}}// 获取文件夹内容@GetMapping("/list")public ResponseResult<List<FileInfo>> listFiles(@RequestParam("userId") String userId,@RequestParam("folderPath") String folderPath) {try {String prefix = String.format("user/%s/%s", userId, folderPath);List<S3Object> objects = s3Service.listFolderContent(prefix);List<FileInfo> fileInfos = objects.stream().filter(obj -> !obj.key().endsWith("/")) // 过滤文件夹标记.map(obj -> {String fileName = obj.key().substring(obj.key().lastIndexOf("/") + 1);return new FileInfo(obj.key(),fileName,obj.size(),obj.lastModified().toString());}).collect(Collectors.toList());return ResponseResult.success(fileInfos);} catch (Exception e) {return ResponseResult.error("获取文件列表失败: " + e.getMessage());}}// 生成下载链接@GetMapping("/download-url")public ResponseResult<String> generateDownloadUrl(@RequestParam("fileKey") String fileKey) {try {String url = s3Service.generatePresignedUrl(fileKey, Duration.ofHours(1));return ResponseResult.success(url);} catch (Exception e) {return ResponseResult.error("生成下载链接失败: " + e.getMessage());}}// 删除文件@DeleteMapping("/delete")public ResponseResult<Void> deleteFile(@RequestParam("fileKey") String fileKey) {try {s3Service.delete(fileKey);return ResponseResult.success();} catch (Exception e) {return ResponseResult.error("删除失败: " + e.getMessage());}}
}
前端实现(Vue.js + Element UI)
  • FileUploader.vue

文件上传组件,支持拖拽和多文件上传,通过 props 接收用户 ID 和目录路径,动态拼接参数上传至 S3,自带进度显示、错误处理和成功通知

<template><div class="file-uploader"><el-uploadclass="upload-demo"drag:action="uploadUrl":headers="headers":multiple="true":data="uploadData":on-success="handleUploadSuccess":on-error="handleUploadError":on-progress="handleUploadProgress"><i class="el-icon-upload"></i><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><div class="el-upload__tip" slot="tip">支持最大50MB的文件上传,仅允许常见文档、图片、视频格式</div></el-upload></div>
</template><script>
import { uploadFile } from '@/api/file';export default {props: {userId: {type: String,required: true},currentFolder: {type: String,default: ''}},data() {return {uploadUrl: '/api/files/upload',uploadData: {},progress: 0};},computed: {headers() {return {'Authorization': `Bearer ${localStorage.getItem('token')}`};}},methods: {handleUploadSuccess(response, file, fileList) {this.$message.success('上传成功');this.$emit('upload-success');},handleUploadError(err, file, fileList) {this.$message.error('上传失败');},handleUploadProgress(event, file, fileList) {this.progress = Math.round(event.percent);}},watch: {userId: {immediate: true,handler(val) {this.uploadData = {userId: val,folderPath: this.currentFolder};}},currentFolder(val) {this.uploadData = {userId: this.userId,folderPath: val};}}
};
</script>
  • FileList.vue

通过 props 接收用户 ID 和当前目录路径,初始化及目录切换时调用接口获取文件列表,以表格形式展示文件名、大小、修改时间,并提供下载和删除操作

<template><div class="file-list"><el-table:data="fileList"stripeborder@row-click="handleRowClick"><el-table-column prop="fileName" label="文件名" min-width="300"><template slot-scope="scope"><i class="el-icon-document" v-if="!scope.row.isFolder"></i><i class="el-icon-folder" v-else></i><span>{{ scope.row.fileName }}</span></template></el-table-column><el-table-column prop="fileSize" label="大小" width="120"><template slot-scope="scope">{{ formatSize(scope.row.fileSize) }}</template></el-table-column><el-table-column prop="lastModified" label="修改时间" width="180"></el-table-column><el-table-column label="操作" width="200"><template slot-scope="scope"><el-buttonsize="mini"@click="handleDownload(scope.row, $event)">下载</el-button><el-buttonsize="mini"type="danger"@click="handleDelete(scope.row, $event)">删除</el-button></template></el-table-column></el-table></div>
</template><script>
import { getFileList, generateDownloadUrl, deleteFile } from '@/api/file';export default {props: {userId: {type: String,required: true},currentFolder: {type: String,default: ''}},data() {return {fileList: []};},created() {this.fetchFileList();},watch: {currentFolder() {this.fetchFileList();}},methods: {async fetchFileList() {try {const res = await getFileList(this.userId, this.currentFolder);this.fileList = res.data;} catch (error) {this.$message.error('获取文件列表失败');}},async handleDownload(file) {try {const res = await generateDownloadUrl(file.fileKey);window.open(res.data);} catch (error) {this.$message.error('获取下载链接失败');}},async handleDelete(file) {this.$confirm('确定要删除此文件吗?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(async () => {try {await deleteFile(file.fileKey);this.$message.success('删除成功');this.fetchFileList();} catch (error) {this.$message.error('删除失败');}}).catch(() => {// 取消操作});},formatSize(bytes) {if (bytes === 0) return '0 B';const k = 1024;const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];const i = Math.floor(Math.log(bytes) / Math.log(k));return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];}}
};
</script>
实现流程

Amazon S3 实现网盘文件上传下载功能时,上传流程为前端将用户选择的文件封装成 FormData 发送至后端接口,后端生成唯一文件键,调用Amazon SDK 将文件以私有权限存入 S3 并返回存储标识;下载流程是前端请求后端生成文件对应预签名 URL,该 URL 携带加密签名且有时间限制,返回后触发浏览器下载;文件列表展示则由前端向后端请求指定用户和目录路径下的文件信息,后端通过 S3 的 listObjectsV2 接口获取数据并处理,将文件名、大小等元数据返回前端渲染展示,实现网盘基础文件管理功能

  • 文件上传流程:前端选择文件后,调用 /api/files/upload 接口后端接收文件,生成唯一 Key,文件上传至 S3,返回存储 Key 给前端
  • 文件下载流程:前端点击下载按钮,调用 /api/files/download-url 接口,后端生成有效期 1 小时的预签名 URL,前端打开 URL 直接下载文件
  • 文件列表展示:前端调用 /api/files/list 接口,传入用户 ID 和文件夹路径,后端通过 S3 的 listObjectsV2 获取文件列表,解析文件元数据(文件名、大小、修改时间)返回给前端

Amazon S3使用场景

在这里插入图片描述

Amazon S3 广泛应用于多类场景:构建数据湖支撑大数据分析、AI、ML 及 HPC 应用以挖掘数据见解;借助强大复制功能实现关键数据备份与还原,满足 RTO、RPO 及合规性要求;通过归档至 S3 Glacier 存储类降低成本并支持数据洞察;还能通过 Amazon PrivateLink 实现混合云存储,在 VPC 中预置私有终端节点,以私有 IP 打通本地与 S3 的直接访问亚马逊云科技

  • 企业级数据存储:支撑网盘、文件管理系统等场景,如博主讲述的基于 Vue + Spring Boot 实现的文件上传下载功能,通过用户隔离路径和预签名 URL 保障数据安全
  • 静态资源托管:存储网站图片、CSS、JS 等静态文件,结合 CloudFront CDN 加速全球访问
  • 大数据与分析:作为数据湖存储原始数据,供 EMR、Athena 等服务进行批量处理和实时分析
  • 备份与归档:利用生命周期管理策略自动将低频访问数据归档至 S3 Glacier,降低存储成本
  • 移动与 IoT 数据收集:接收设备日志、用户行为数据等海量流式数据,支持高并发写入和持久化存储

总结

Amazon S3 是高效且灵活的对象存储方案:注册账号后可快速创建存储桶,通过 IAM 实现权限隔离;后端用 Spring Boot 集成 Amazon SDK 完成配置与文件操作(如唯一路径生成、预签名 URL 控制下载时效),前端借助 Vue + Element UI 组件实现交互(拖拽上传、表格展示);利用伪文件夹机制和用户 ID 分层可构建网盘目录,结合版本控制、生命周期管理等功能,能低成本实现数据安全、备份与成本优化,适合企业网盘、静态资源托管、大数据分析等场景,与云原生技术栈集成可显著提升开发运维效率。

友情提示:如果决定不再使用服务的话,记得要在控制台关闭服务,以防超过免费额度产生扣费

http://www.lryc.cn/news/583076.html

相关文章:

  • 1.1 ARMv8/ARMv9安全扩展
  • ReactNative【实战】轮播图(含组件封装 ImageSlider)
  • 洛谷P1044 栈(学习向)
  • react16-react19都更新哪些内容?
  • clickhouse 各个引擎适用的场景
  • 【TCP/IP】2. 计算机网络与因特网体系结构
  • 手机文件夹隐藏工具,一键保护隐私
  • 数据库性能优化指南:解决ORDER BY导致的查询性能问题( SQL Server )
  • Dify 文本语意识别与自动补全工作流
  • MyBatisPlus-03-扩展功能
  • C#基础篇(11)泛型类与泛型方法详解
  • 1068.产品销售分析Ⅰ
  • huggingface 笔记: Trainer
  • 打造自己的组件库(二)CSS工程化方案
  • 跨服务sqlplus连接oracle数据库
  • 54页|PPT|新型数字政府综合解决方案:“一网 一云 一中台 N应用”平台体系 及“安全+运营”服务体系
  • 人工智能的基石:TensorFlow与PyTorch在图像识别和NLP中的应用
  • 影石(insta360)X4运动相机视频删除的恢复方法
  • 【视频观看系统】- 需求分析
  • 【DB2】load报错SQL3501W、SQL3109N、SQL2036N
  • Tensorflow的安装记录
  • django 一个表中包括id和parentid,如何通过parentid找到全部父爷id
  • react+ts 移动端页面分页,触底加载下一页
  • 板凳-------Mysql cookbook学习 (十一--------6)
  • 安卓设备信息查看器 - 源码编译
  • Android-重学kotlin(协程源码第二阶段)新学习总结
  • 中望CAD2026亮点速递(5):【相似查找】高效自动化识别定位
  • uniapp AndroidiOS 定位权限检查
  • Android ViewModel机制与底层原理详解
  • upload-labs靶场通关详解:第19关 条件竞争(二)