在博主得到系统中使用的对象存储主要有OSS(阿里云的对象存储) COS(腾讯云的对象存储)OBS(华为云的对象存储)还有就是MinIO 这些玩意。其实这种东西大差不差,几乎实现方式都是一样,存储模式大同小异。下面介绍几种存储模式在springBoot中的使用。
阿里云对象存储服务(Object Storage Service,简称OSS)是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。它具有与平台无关的RESTful API接口,能够提供99.999999999%(11个9)的数据可靠性和99.99%的服务可用性。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
基于OSS,用户可以搭建出各种多媒体分享网站、网盘、个人和企业数据备份等基于大规模数据的服务。OSS非常适合用来存储大量不同大小、格式的非结构化数据,比如视频、图像、文本、日志等,且单个文件最大支持48.8TB,不限文件数量和大小。同时,OSS提供多种存储类型,包括标准存储、低频存储和归档存储,用户可以根据需求选择相应的存储类型。
在使用OSS时,用户可以通过阿里云控制台、图形化工具和命令行工具对数据进行上传、下载和管理。此外,OSS还提供了简单的REST接口,使得用户可以在任何互联网设备上进行数据的上传和下载。
关于OSS的定价和计量计费方式,阿里云提供了详细的说明。用户在使用OSS时,需要注意相关的使用限制和错误码,以确保服务的正常使用。
1、引入依赖
com.aliyun.oss aliyun-sdk-oss${aliyun-sdk-oss.version}
2、读取配置
@Data @Component @ConfigurationProperties(prefix = "oss.aliyun") public class AliYunProperties { /**域名*/ private String domain; /**地域节点*/ private String endpoint; /**存储桶名称*/ private String bucketName; /**accessKey*/ private String accessKey; /**accessSecret*/ private String accessSecret; /**图片策略*/ private String styleRule; /**缩略图策略*/ private String thumbnailStyleRule; /**文件类型*/ private ListfileTypes; }
3、实现图片上传
@Slf4j @Component("aliyun") public class AliYunFileHandle implements FileStrategy { @Autowired AliYunProperties aliYunProperties; private static OSS ossClient; @Override public UploadDto upload(MultipartFile file) throws Exception { return upload(file, null); } @Override public UploadDto upload(MultipartFile file, String filePath) throws Exception { //文件名 String fileFullName = FileUtil.getName(file.getOriginalFilename()); InputStream inputStream = file.getInputStream(); return upload(inputStream, fileFullName, filePath); } public UploadDto upload(InputStream inputStream, String fileFullName, String filePath) throws Exception { if (inputStream == null) { throw new Exception("上传文件不能为空"); } OSS ossClient = getOssClient(); try { //时间戳 String timestamp = String.valueOf(System.currentTimeMillis()); //文件扩展名 String extension = FileUtil.getSuffix(fileFullName); String fileName = FileUtil.getPrefix(fileFullName); ListfileTypes = aliYunProperties.getFileTypes(); if(fileTypes != null) { boolean flag= fileTypes.contains(extension); Assert.isTrue(flag, "不支持上传的文件类型:" + extension); } String upFilePath = StringUtils.join(fileName, "_", timestamp, ".", extension); if(filePath != null) { upFilePath = StringUtils.join(filePath, "/", upFilePath); } //String upFilePath = StringUtils.join(encodeName, ".", extension); // 文件上传 PutObjectResult putObjectResult = ossClient.putObject(aliYunProperties.getBucketName(), upFilePath, inputStream); if (putObjectResult == null) { log.error("上传附件到阿里云失败 fileName={}", upFilePath); throw new Exception("上传附件 " + upFilePath + " 到阿里云失败 "); } log.info("oss fileName:" + upFilePath); //返回上传结果 UploadDto uploadDto = new UploadDto(); uploadDto.setName(upFilePath); // uploadDto.setImgUrl(filePath); // uploadDto.setKey(upFilePath); uploadDto.setCreateTime(DateUtil.date()); // //缩略图处理 // if (isImageType(uploadDto.getMediaType())) { // BufferedImage image = ImageIO.read(file.getInputStream()); // uploadDto.setWidth(image.getWidth()); // uploadDto.setHeight(image.getHeight()); // uploadDto.setThumbPath(StringUtils.isBlank(aliYunProperties.getThumbnailStyleRule()) ? filePath : filePath + aliYunProperties.getThumbnailStyleRule()); // } return uploadDto; } catch (Exception e) { log.error("oss 上传失败", e); throw new RuntimeException("文件="+fileFullName + " 上传失败"); } finally { ossClient.shutdown(); } } private OSS getOssClient() { // 调用了shutdown方法,暂时不使用连接池方式 // if(ossClient == null) { ossClient = new OSSClientBuilder().build(aliYunProperties.getEndpoint(), aliYunProperties.getAccessKey(), aliYunProperties.getAccessSecret()); // } return ossClient; } @Override public byte[] download(String key) throws Exception { if (key == null) { throw new Exception("文件key不能为空"); } OSS ossClient = getOssClient(); try { // 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt OSSObject ossObject = ossClient.getObject(new GetObjectRequest(aliYunProperties.getBucketName(), key)); return IoUtil.readBytes(ossObject.getObjectContent()); } catch (Exception e) { e.printStackTrace(); } finally { ossClient.shutdown(); } return null; } @Override public void delete(String key) { } }
腾讯云对象存储(Cloud Object Storage,COS)是一种分布式存储服务,专为存储海量文件而设计。用户可以通过网络随时存储和查看数据,享受高扩展性、低成本、可靠且安全的数据存储服务。
COS通过控制台、API、SDK和工具等多样化方式,简单、快速地接入,实现海量数据存储和管理。用户可以轻松进行任意格式文件的上传、下载和管理,一个存储桶可容纳无数个对象。对象(Object)是COS的基本单元,可以理解为任何格式类型的数据,例如图片、文档和音视频文件等。
根据访问频度的高低,COS提供三种对象的存储级别:标准存储、低频存储和归档存储。标准存储为用户提供了高可靠性、高可用性和高性能的对象存储服务,适用于有大量热点文件,需要频繁访问数据的业务场景,如热点视频、社交图片等。低频存储则适用于不频繁访问数据的存储,如网盘数据、大数据分析等,它同样提供高可靠性,但存储成本和访问时延相对较低。
此外,腾讯云还提供了COSBrowser这一桌面版工具,用户可以使用该工具进行可视化、方便的数据上传、下载等操作。这些功能使得COS成为一个强大且灵活的云存储解决方案,能够满足各种业务类型的存储需求。
1、引入依赖
com.qcloud cos_api${cos_api.version}
2、读取配置
@Data @Component @ConfigurationProperties(prefix = "oss.tencent") public class TencentProperties { /**域名*/ private String domain; /**地域节点*/ private String region; /**存储桶名称*/ private String bucketName; /**secretId*/ private String secretId; /**secretKey*/ private String secretKey; /**图片策略*/ private String styleRule; /**缩略图策略*/ private String thumbnailStyleRule; /**文件类型*/ private ListfileTypes; }
3、文件上传下载
@Slf4j @Component("tencent") public class TencentFileHandle implements FileStrategy { @Autowired TencentProperties tencentProperties; // 创建 COSClient 实例,这个实例用来后续调用请求 COSClient createCOSClient() { // 设置用户身份信息。 // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理 String secretId = tencentProperties.getSecretId(); String secretKey = tencentProperties.getSecretKey(); COSCredentials cred = new BasicCOSCredentials(secretId, secretKey); // ClientConfig 中包含了后续请求 COS 的客户端设置: ClientConfig clientConfig = new ClientConfig(); // 设置 bucket 的地域 // COS_REGION 请参照 https://cloud.tencent.com/document/product/436/6224 clientConfig.setRegion(new Region(tencentProperties.getRegion())); // 设置请求协议, http 或者 https // 5.6.53 及更低的版本,建议设置使用 https 协议 // 5.6.54 及更高版本,默认使用了 https clientConfig.setHttpProtocol(HttpProtocol.https); // 以下的设置,是可选的: // 设置 socket 读取超时,默认 30s clientConfig.setSocketTimeout(30*1000); // 设置建立连接超时,默认 30s clientConfig.setConnectionTimeout(30*1000); // 如果需要的话,设置 http 代理,ip 以及 port // clientConfig.setHttpProxyIp("httpProxyIp"); // clientConfig.setHttpProxyPort(80); // 生成 cos 客户端。 return new COSClient(cred, clientConfig); } // 创建 TransferManager 实例,这个实例用来后续调用高级接口 TransferManager createTransferManager() { // 创建一个 COSClient 实例,这是访问 COS 服务的基础实例。 // 详细代码参见本页: 简单操作 -> 创建 COSClient COSClient cosClient = createCOSClient(); // 自定义线程池大小,建议在客户端与 COS 网络充足(例如使用腾讯云的 CVM,同地域上传 COS)的情况下,设置成16或32即可,可较充分的利用网络资源 // 对于使用公网传输且网络带宽质量不高的情况,建议减小该值,避免因网速过慢,造成请求超时。 ExecutorService threadPool = Executors.newFixedThreadPool(32); // 传入一个 threadpool, 若不传入线程池,默认 TransferManager 中会生成一个单线程的线程池。 TransferManager transferManager = new TransferManager(cosClient, threadPool); // 设置高级接口的配置项 // 分块上传阈值和分块大小分别为 5MB 和 1MB TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration(); transferManagerConfiguration.setMultipartUploadThreshold(5*1024*1024); transferManagerConfiguration.setMinimumUploadPartSize(1*1024*1024); transferManager.setConfiguration(transferManagerConfiguration); return transferManager; } void shutdownTransferManager(TransferManager transferManager) { // 指定参数为 true, 则同时会关闭 transferManager 内部的 COSClient 实例。 // 指定参数为 false, 则不会关闭 transferManager 内部的 COSClient 实例。 transferManager.shutdownNow(true); } @Override public UploadDto upload(MultipartFile file) throws Exception { return upload(file, null); } @Override public UploadDto upload(MultipartFile file, String filePath) throws Exception { //文件名 String fileFullName = FileUtil.getName(file.getOriginalFilename()); InputStream inputStream = file.getInputStream(); return upload(inputStream, fileFullName, filePath); } public UploadDto upload(InputStream inputStream, String fileFullName, String filePath) throws Exception { if (inputStream == null) { throw new Exception("上传文件不能为空"); } TransferManager transferManager = createTransferManager(); String bucketName = tencentProperties.getBucketName(); //int inputStreamLength = 1024 * 1024; // byte data[] = new byte[inputStreamLength]; // InputStream inputStream = new ByteArrayInputStream(data); ObjectMetadata objectMetadata = new ObjectMetadata(); // 上传的流如果能够获取准确的流长度,则推荐一定填写 content-length // 如果确实没办法获取到,则下面这行可以省略,但同时高级接口也没办法使用分块上传了 //objectMetadata.setContentLength(inputStreamLength); try { //时间戳 String timestamp = String.valueOf(System.currentTimeMillis()); //文件扩展名 String extension = FileUtil.getSuffix(fileFullName); String fileName = FileUtil.getPrefix(fileFullName); ListfileTypes = tencentProperties.getFileTypes(); if(fileTypes != null) { boolean flag= fileTypes.contains(extension); Assert.isTrue(flag, "不支持上传的文件类型:" + extension); } String upFilePath = StringUtils.join(fileName, "_", timestamp, ".", extension); if(filePath != null) { upFilePath = StringUtils.join(filePath, "/", upFilePath); } String key = upFilePath; PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, objectMetadata); // 高级接口会返回一个异步结果Upload // 可同步地调用 waitForUploadResult 方法等待上传完成,成功返回UploadResult, 失败抛出异常 Upload upload = transferManager.upload(putObjectRequest); UploadResult uploadResult = upload.waitForUploadResult(); if (uploadResult == null) { log.error("上传附件到腾讯云失败 fileName={}", upFilePath); throw new Exception("上传附件 " + upFilePath + " 到腾讯云失败 "); } log.info("cos fileName:" + upFilePath); //返回上传结果 UploadDto uploadDto = new UploadDto(); uploadDto.setName(upFilePath); // uploadDto.setKey(upFilePath); uploadDto.setCreateTime(DateUtil.date()); return uploadDto; } catch (Exception e) { log.error("cos 上传失败", e); throw new RuntimeException("文件="+fileFullName + " 上传失败"); } finally { shutdownTransferManager(transferManager); } } @Override public byte[] download(String key) throws Exception { return null; } @Override public void delete(String key) { } }
华为云OBS,即华为云对象存储服务(Object Storage Service),是华为云提供的一种简单、高效、安全的云存储解决方案。它基于对象存储架构,为用户提供了海量、安全、高可靠、低成本的数据存储能力,且无需考虑容量限制。
华为云OBS具有以下主要特点和功能:
此外,华为云OBS还提供了多种存储类型供用户选择,以满足不同业务场景的需求。同时,它与其他华为云服务和产品无缝集成,为用户提供一站式云计算基础设施服务体验。
1、引入依赖
com.obs obs3.2.5
2、需要的配置
华为云OBS存储桶名称 obs.bucketName=your-bucket-name #华为云OBS服务节点,如上海(China East) obs.endpoint=http://your-endpoint #华为云OBS账户AK obs.accessKey=your-access-key-id #华为云OBS账户SK obs.secretKey=your-secret-access-key
3、代码实现
import com.obs.services.ObsClient; import com.obs.services.model.PutObjectRequest; import com.obs.services.model.PutObjectResult; public class OBSExample { public static void main(String[] args) { // 填入你的OBS访问密钥、秘钥和地址 String accessKey = "你的Access Key"; String secretKey = "你的Secret Key"; String endPoint = "你的End Point"; String bucketName = "你的Bucket Name"; String objectKey = "你要上传的Object Key"; String filePath = "文件路径"; try { // 创建ObsClient实例 ObsClient obsClient = new ObsClient(accessKey, secretKey, endPoint); // 创建上传请求 PutObjectRequest request = new PutObjectRequest(); request.setBucketName(bucketName); // 设置Bucket名称 request.setObjectKey(objectKey); // 设置Object名称 request.setFilePath(filePath); // 设置文件路径 // 上传文件 PutObjectResult result = obsClient.putObject(request); System.out.println("Upload file successfully, ETag:" + result.getETag()); // 关闭ObsClient实例 obsClient.close(); } catch (Exception e) { e.printStackTrace(); } } }
Minio是GlusterFS创始人之一Anand Babu Periasamy发布新的开源项目。基于Apache License v2.0开源协议的对象存储项目,采用Golang实现,客户端支Java,Python,Javacript, Golang语言。
其设计的主要目标是作为私有云对象存储的标准方案。主要用于存储海量的图片,视频,文档等。非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
实现也差不多。