SpringBoot项目集成亚马逊的S3对象存储

pom文件导入依赖

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.amazonaws</groupId>
                <artifactId>aws-java-sdk-bom</artifactId>
                <version>1.12.642</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>
<dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
        </dependency>
</dependencies>

yml配置:
aws:accessKey: xxxxxxsecretKey: xxxxxxendPoint: http://10.10.10.1:443bucketName: bucket-test01
组装客户端Service
package com.susu.service;import com.amazonaws.services.s3.model.CompleteMultipartUploadResult;
import com.amazonaws.services.s3.model.PutObjectResult;import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;public interface EdsOssFileUploadService {/*** 高级API大文件分片上传* @param keyName 唯一文件标识* @param file file* @return keyName 唯一文件标识* @throws InterruptedException*/String highLevelMultipartUpload(String keyName, File file) throws InterruptedException;/*** 文件分片上传* @param keyName 唯一文件标识* @param bucketName 桶名称* @param file file* @return CompleteMultipartUploadResult*/CompleteMultipartUploadResult bigFileListShardingUpload(String keyName, String bucketName, File file);/*** 文件分片上传* @param keyName 唯一文件标识* @param file file* @return CompleteMultipartUploadResult*/CompleteMultipartUploadResult bigFileListShardingUpload(String keyName, File file);/***  文件分片上传 指定桶* @param bucketName 桶名称* @param fileInputStream 文件流* @param fileContentLength  原始文件的length* @param keyName 唯一文件标识* @return CompleteMultipartUploadResult*/CompleteMultipartUploadResult uploadLargeFileToS3(String bucketName, FileInputStream fileInputStream, long fileContentLength, String keyName);/***  文件分片上传 默认桶* @param fileInputStream 文件流* @param fileLength 原始文件的length* @param key 唯一文件标识* @return CompleteMultipartUploadResult*/CompleteMultipartUploadResult uploadLargeFileToS3(FileInputStream fileInputStream, long fileLength, String key);/*** 文件下载* @param key 唯一文件标识* @param bucketName  桶名称* @return InputStream*/InputStream downloadToEDS(String key, String bucketName);/*** 文件下载  默认桶* @param key 唯一文件标识* @return InputStream*/InputStream downloadToEDS(String key);/*** 简单文件上传 --流 指定桶* @param keyName 唯一文件标识* @param inputStream 文件流* @param bucketName 桶名称* @return PutObjectResult*/PutObjectResult streamUploadToEDS(String keyName, InputStream inputStream, String bucketName);/*** 简单文件上传 --流 默认桶* @param keyName 唯一文件标识* @param inputStream 文件流* @return PutObjectResult*/PutObjectResult streamUploadToEDS(String keyName, InputStream inputStream);/***  简单文件上传 --file 指定桶* @param keyName 唯一文件标识* @param file 文件* @param bucketName 桶名称* @return PutObjectResult*/PutObjectResult simpleUploadToEDS(String keyName, File file, String bucketName);/***  简单文件上传 --file 默认桶* @param keyName 唯一文件标识* @param file 文件* @return PutObjectResult*/PutObjectResult simpleUploadToEDS(String keyName, File file);/*** 创建文件上传的预签名--URL* @param bucketName 桶名称* @param keyName 唯一文件标识* @return URL*/URL createSignedUrlForStringPut(String bucketName, String keyName);/*** 创建文件下载的预签名--URL* @param bucketName 桶名称* @param keyName 唯一文件标识* @return URL*/URL createSignedUrlForStringGet(String bucketName, String keyName);
}
组装客户端Impl
package com.susu.service.impl;import cn.hutool.core.util.IdUtil;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.HttpMethod;
import com.amazonaws.Protocol;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;
import com.amazonaws.services.s3.transfer.model.UploadResult;
import com.susu.service.EdsOssFileUploadService;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.amazonaws.retry.RetryPolicy;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;@Service
@Data
public class EdsOssFileUploadServiceImpl implements EdsOssFileUploadService {private Logger logger = LoggerFactory.getLogger(EdsOssFileUploadServiceImpl.class);/*** access key :示例L8O3KRQZTXGVDIBQ0WON*/@Value("${aws.accessKey}")private String accessKey;/*** secret key:示例Bm0kLoFdLu70RKTOtjdP5Q9oOVDgEXHOmbrelxeb*/@Value("${aws.secretKey}")private String secretKey;/*** 地址:对象存储服务的端口号:示例http://10.212.27.56:12001*/@Value("${aws.endPoint}")private String endPoint;/*** bucket名称:示例eds-cloud-oss*/@Value("${aws.bucketName}")private String bucketName;/*** region:示例cn-north-1*//*@Value("${aws.region}")private String region;*/private AmazonS3 amazonS3Client;private TransferManager transferManager;@Autowired@Qualifier("asyncTaskExecutor")private Executor threadPoolTaskExecutor;@PostConstructpublic void init() {AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);ClientConfiguration clientConfig = new ClientConfiguration();clientConfig.setSignerOverride("AWSS3V4SignerType");clientConfig.setProtocol(Protocol.HTTP);clientConfig.setConnectionTimeout(300000);clientConfig.setClientExecutionTimeout(300000);clientConfig.setConnectionMaxIdleMillis(300000);clientConfig.setRetryPolicy(new RetryPolicy(null,null,3,true));// 初始化AmazonS3Clientthis.amazonS3Client = AmazonS3ClientBuilder.standard().withClientConfiguration(clientConfig).withCredentials(new AWSStaticCredentialsProvider(credentials)).withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, "")).withPathStyleAccessEnabled(true).build();// 配置自定义线程池int availableProcessor = Runtime.getRuntime().availableProcessors();ThreadPoolExecutor threadPool = new ThreadPoolExecutor(availableProcessor + 1,(availableProcessor + 1) * 2,60,  // 非核心线程空闲时间TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(200),new ThreadPoolExecutor.CallerRunsPolicy());this.transferManager = TransferManagerBuilder.standard().withS3Client(amazonS3Client).withExecutorFactory(()-> threadPool).build();}/*** AWS SDK 公开了一个名为 TransferManager 的高级别 API,用于简化分段上传。有关更多信息,请参阅 使用分段上传来上传和复制对象。* <p>* 您可以从文件或流上传数据。您还可以设置高级选项,例如,您想要用于分段上传的分段大小或在上传分段时要使用的并发线程数。* 您也可以设置可选的对象属性、存储类或访问控制列表 (ACL)。您可以使用 PutObjectRequest 和 TransferManagerConfiguration 类来设置这些高级选项。** @param keyName keyName* @param file    file* @return CompleteMultipartUploadResult*/@Overridepublic String highLevelMultipartUpload(String keyName, File file) {// 使用 TransferManager 上传try {Upload upload = transferManager.upload(bucketName, keyName, file);upload.waitForCompletion();String url = amazonS3Client.getUrl(bucketName, keyName).toString();logger.info("上传文件完成,地址:{}", url);return url;}catch (Exception e ){logger.error("上传文件异常:{}",e);}return null;}/*** EDS提供的分片上传(Multipart Upload)功能,将要上传的较大文件(object)分成多个分片(Part)来分别上传* 上传完成后再调用completeMultipartUpload接口将这些Part组合成一个object来达到断点续传的效果。** @param keyName    keyName* @param bucketName yourBucketName* @param file       file* @return CompleteMultipartUploadResult*/@Overridepublic CompleteMultipartUploadResult bigFileListShardingUpload(String keyName, String bucketName, File file) {List<PartETag> partETags = new ArrayList<>();long filePosition = 0;CompleteMultipartUploadResult result = null;String uploadId = null;InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, keyName);InitiateMultipartUploadResult initResponse = amazonS3Client.initiateMultipartUpload(initRequest);uploadId = initResponse.getUploadId();try {long contentLength = file.length();long partSize = 25 * 1024 * 1024; // Set part size to 25 MB.logger.info("-------开始只能进入分片上传阶段-------");for (int i = 1; filePosition < contentLength; i++) {partSize = Math.min(partSize, (contentLength - filePosition));UploadPartRequest uploadRequest = new UploadPartRequest().withBucketName(bucketName).withKey(keyName).withUploadId(uploadId).withPartNumber(i).withFileOffset(filePosition).withFile(file).withPartSize(partSize);UploadPartResult uploadResult = amazonS3Client.uploadPart(uploadRequest);// 返回文件的ETag值,用于验证文件是否被正确上传partETags.add(uploadResult.getPartETag());filePosition += partSize;logger.info("文件分片上传--->" + filePosition);}logger.info("-------所有分片上传完整------->进入分片合并阶段-------");// 完成分片上传CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucketName, keyName, initResponse.getUploadId(), partETags);result = amazonS3Client.completeMultipartUpload(compRequest);logger.info("Object upload complete,地址:{}",result.getLocation().toString());} catch (SdkClientException e) {logger.error("分片上传错误,第{}片发生意外", filePosition, e);throw new RuntimeException(e);}logger.info("-------大文件分片上传完成--->" + filePosition);return result;}@Overridepublic CompleteMultipartUploadResult bigFileListShardingUpload(String keyName, File file) {return bigFileListShardingUpload(keyName, bucketName, file);}/*** 分片上传** @param bucketName        桶名称* @param fileInputStream   文件流* @param fileContentLength 原始文件的length* @param keyName           唯一文件标识* @return*/@Overridepublic CompleteMultipartUploadResult uploadLargeFileToS3(String bucketName, FileInputStream fileInputStream, long fileContentLength, String keyName) {InitiateMultipartUploadResult initResponse = null;InitiateMultipartUploadRequest initRequest = null;CompleteMultipartUploadResult completeMultipartUploadResult = null;try {// 初始化多部分上传initRequest = new InitiateMultipartUploadRequest(bucketName, keyName);initResponse = amazonS3Client.initiateMultipartUpload(initRequest);// 每个分片大小(例如:5MB)long partSize = 5 * 1024 * 1024;List<PartETag> partETags = new ArrayList<>();long bytePosition = 0;for (int i = 1; bytePosition < fileContentLength; i++) {long bytesRemaining = fileContentLength - bytePosition;partSize = Math.min(bytesRemaining, partSize);UploadPartRequest uploadRequest = new UploadPartRequest().withBucketName(bucketName).withKey(keyName).withUploadId(initResponse.getUploadId()).withPartNumber(i).withFileOffset(bytePosition).withInputStream(fileInputStream).withPartSize(partSize);UploadPartResult uploadResult = amazonS3Client.uploadPart(uploadRequest);partETags.add(uploadResult.getPartETag());bytePosition += partSize;}// 完成多部分上传CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucketName, keyName, initResponse.getUploadId(), partETags);completeMultipartUploadResult = amazonS3Client.completeMultipartUpload(compRequest);} catch (SdkClientException e) {// 处理异常,可能需要回滚已上传的部分logger.error("Error uploading file to S3", e);// 如果有错误,尝试取消上传AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest(bucketName, keyName, initResponse.getUploadId());amazonS3Client.abortMultipartUpload(abortMPURequest);} finally {try {fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}return completeMultipartUploadResult;}@Overridepublic CompleteMultipartUploadResult uploadLargeFileToS3(FileInputStream fileInputStream, long fileLength, String key) {return uploadLargeFileToS3(bucketName, fileInputStream, fileLength, key);}/*** 简单下载文件流** @param key key* @return InputStream*/@Overridepublic InputStream downloadToEDS(String key, String bucketName) {logger.info("Downloading {} from S3 bucket {}...\n", key, bucketName);S3Object object = amazonS3Client.getObject(new GetObjectRequest(bucketName, key));return object.getObjectContent();}@Overridepublic InputStream downloadToEDS(String key) {return downloadToEDS(key, bucketName);}/*** 流式上传文件到EDS** @param keyName     fileName* @param inputStream InputStream* @return PutObjectResult*/@Overridepublic PutObjectResult streamUploadToEDS(String keyName, InputStream inputStream, String bucketName) {try {//创建上传Object的MetadataObjectMetadata metadata = new ObjectMetadata();//上传的文件的长度metadata.setContentLength(inputStream.available());//指定该Object被下载时的网页的缓存行为metadata.setCacheControl("no-cache");//指定该Object下设置Headermetadata.setHeader("Pragma", "no-cache");//指定该Object被下载时的内容编码格式metadata.setContentEncoding("utf-8");//文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,//如果没有扩展名则填默认值application/octet-streammetadata.setContentType("application/octet-stream");return amazonS3Client.putObject(bucketName, keyName, inputStream, metadata);} catch (IOException e) {logger.error("文件上传失败。。。。" + e.getMessage());throw new RuntimeException(e);} catch (SdkClientException e) {throw new RuntimeException(e);}}@Overridepublic PutObjectResult streamUploadToEDS(String keyName, InputStream inputStream) {return streamUploadToEDS(keyName, inputStream, bucketName);}/*** 简单上传文件到EDS** @param keyName fileName* @param file    file* @return PutObjectResult*/@Overridepublic PutObjectResult simpleUploadToEDS(String keyName, File file, String bucketName) {return amazonS3Client.putObject(bucketName, keyName, file);}@Overridepublic PutObjectResult simpleUploadToEDS(String keyName, File file) {return amazonS3Client.putObject(bucketName, keyName, file);}/*** 创建文件上传的预签名--URL** @param bucketName 桶名称* @param keyName    唯一文件标识* @return URL*/@Overridepublic URL createSignedUrlForStringPut(String bucketName, String keyName) {Date expiration = new Date();long expirationNumber = expiration.getTime() + 3600 * 1000;expiration.setTime(expirationNumber);GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, keyName, HttpMethod.PUT);generatePresignedUrlRequest.setExpiration(expiration);return amazonS3Client.generatePresignedUrl(generatePresignedUrlRequest);}/*** 创建文件下载的预签名--URL** @param bucketName 桶名称* @param keyName    唯一文件标识* @return URL*/@Overridepublic URL createSignedUrlForStringGet(String bucketName, String keyName) {Date expiration = new Date();long expirationNumber = expiration.getTime() + 3600 * 1000;expiration.setTime(expirationNumber);GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, keyName, HttpMethod.GET);generatePresignedUrlRequest.setExpiration(expiration);return amazonS3Client.generatePresignedUrl(generatePresignedUrlRequest);}
}
SpringBoot测试
@SpringBootTest(classes = FilestoreApplication.class)
@Import(EdsOssFileUploadServiceImpl.class)
public class FilestoreApplicationTest {private Logger logger = LoggerFactory.getLogger(FilestoreApplicationTest.class);@Autowiredprivate EdsOssFileUploadService edsOssFileUploadService;/*** 文件上传EDS云对象存储测试:通过* <p>* 2024-03-06 14:07:03.079  INFO 15144 --- [           main] c.c.c.f.FilestoreApplicationTest         : Started FilestoreApplicationTest in 2.059 seconds (JVM running for 2.728)* 2024-03-06 14:07:03.270  INFO 15144 --- [           main] c.c.c.f.FilestoreApplicationTest         : 上传生成的=26438e0c-e379-4343-b645-03e8056baaf6/硬件检测.jpg* 2024-03-06 14:07:03.628  INFO 15144 --- [           main] c.c.c.f.a.i.EdsOssFileUploadServiceImpl  : -------开始只能进入分片上传阶段-------* 2024-03-06 14:07:03.918  INFO 15144 --- [           main] c.c.c.f.a.i.EdsOssFileUploadServiceImpl  : 文件分片上传--->196369* 2024-03-06 14:07:03.919  INFO 15144 --- [           main] c.c.c.f.a.i.EdsOssFileUploadServiceImpl  : -------所有分片上传完整------->进入分片合并阶段-------* 2024-03-06 14:07:03.969  INFO 15144 --- [           main] c.c.c.f.a.i.EdsOssFileUploadServiceImpl  : -------大文件分片上传完成--->196369* 2024-03-06 14:07:03.969  INFO 15144 --- [           main] c.c.c.f.FilestoreApplicationTest         : 上传执行时间(ms):699* 2024-03-06 14:07:03.969  INFO 15144 --- [           main] c.c.c.f.FilestoreApplicationTest         : 上传成功:1afe99dec706c24e174f5d22e08b48b7-1*/@Testvoid contextLoads() {try {File fileLocal = new File("D:\\硬件检测.jpg");String originalFilename = fileLocal.getName();String key = UUID.randomUUID() + "/" + originalFilename;logger.info("上传生成的=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();CompleteMultipartUploadResult result = edsOssFileUploadService.bigFileListShardingUpload(key, fileLocal);stopWatch.stop();logger.info("上传执行时间(ms):" + stopWatch.getTotalTimeMillis());// 处理上传结果String eTag = result.getETag();// ...logger.info("上传成功:" + eTag);} catch (Exception e) {logger.error("上传失败", e);}}/*** 高级API大文件上传EDS云对象存储测试*/@Testvoid contextLoadsBigFile() {try {File fileLocal = new File("D:\\fileTemp\\深信服OSS\\aws-java-sdk-1.12.643.zip");String originalFilename = fileLocal.getName();String key = UUID.randomUUID() + "/" + originalFilename;logger.info("上传生成的=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();String eTag = edsOssFileUploadService.highLevelMultipartUpload(key, fileLocal);stopWatch.stop();logger.info("上传执行时间(ms):" + stopWatch.getTotalTimeMillis());// ...logger.info("上传成功:" + eTag);} catch (Exception e) {logger.error("上传失败", e);}}/*** 分片API大文件上传EDS云对象存储测试*/@Testvoid contextLoadsBigFileShare() {try {File fileLocal = new File("D:\\fileTemp\\深信服OSS\\aws-java-sdk-1.12.643.zip");String originalFilename = fileLocal.getName();String key = UUID.randomUUID() + "/" + originalFilename;logger.info("上传生成的=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();CompleteMultipartUploadResult result = edsOssFileUploadService.uploadLargeFileToS3(new FileInputStream(fileLocal), fileLocal.length(), key);stopWatch.stop();logger.info("上传执行时间(ms):" + stopWatch.getTotalTimeMillis());// 处理上传结果String eTag = result.getETag();// ...logger.info("上传成功:" + eTag);} catch (Exception e) {logger.error("上传失败", e);}}/*** 文件下载*/@Testvoid contextLoadsDownFile() {try {String key = "26438e0c-e379-4343-b645-03e8056baaf6/硬件检测.jpg";logger.info("文件下载的key=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();InputStream inputStream = edsOssFileUploadService.downloadToEDS(key);stopWatch.stop();logger.info("文件下载执行时间(ms):" + stopWatch.getTotalTimeMillis());// 处理结果if (inputStream != null) {// ...logger.info("文件下载:");}} catch (Exception e) {logger.error("文件下载", e);}}/*** 预签名URL+文件下载: 测试通过* 2024-03-06 14:10:26.721  INFO 29356 --- [           main] c.c.c.f.FilestoreApplicationTest         : 文件下载的key=26438e0c-e379-4343-b645-03e8056baaf6/硬件检测.jpg* 2024-03-06 14:10:26.763  INFO 29356 --- [           main] c.c.c.f.FilestoreApplicationTest         : 文件下载执行时间(ms):41* 2024-03-06 14:10:26.763  INFO 29356 --- [           main] c.c.c.f.FilestoreApplicationTest         : 文件下载:http://10.1.2.16:12001/digtal_resources/26438e0c-e379-4343-b645-03e8056baaf6/%E7%A1%AC%E4%BB%B6%E6%A3%80%E6%B5%8B.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20240306T061026Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3599&X-Amz-Credential=MOTNMUS8FJ8P3YTXQSB5%2F20240306%2F%2Fs3%2Faws4_request&X-Amz-Signature=9536999bbc0f1b6de5bb3cf910af0def5ee1f04389446a1688724f27d5655e65*/@Testvoid createSignedUrlForStringGet() {try {String key = "26438e0c-e379-4343-b645-03e8056baaf6/硬件检测.jpg";logger.info("文件下载的key=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();URL url = edsOssFileUploadService.createSignedUrlForStringGet("digtal_resources", key);stopWatch.stop();logger.info("文件下载执行时间(ms):" + stopWatch.getTotalTimeMillis());// 处理结果if (url != null) {// ...logger.info("文件下载:" + url);}} catch (Exception e) {logger.error("文件下载", e);}}/*** 预签名文件上传*/@Testvoid createSignedUrlForStringPut() {try {String key = "26438e0c-e379-4343-b645-03e8056baaf6/硬件检测.jpg";logger.info("文件上传的key=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();URL url = edsOssFileUploadService.createSignedUrlForStringPut("digtal_resources", key);stopWatch.stop();logger.info("文件上传执行时间(ms):" + stopWatch.getTotalTimeMillis());// 处理结果if (url != null) {// ...logger.info("文件上传:" + url);}} catch (Exception e) {logger.error("文件上传", e);}}
}
写在最后

如果发现上传后,无法访问返回的地址,可以尝试从返回地址下载!!!

@GetMapping("/test1")public void contextLoads() {try {File fileLocal = new File("D:\\a.png");String originalFilename = fileLocal.getName();String key = UUID.randomUUID() +SEPARATOR + originalFilename;logger.info("上传生成的=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();CompleteMultipartUploadResult result = edsOssFileUploadService.bigFileListShardingUpload(key, fileLocal);stopWatch.stop();logger.info("上传执行时间(ms):" + stopWatch.getTotalTimeMillis());// 处理上传结果String eTag = result.getETag();// ...logger.info("上传成功:" + eTag);logger.info(result.getLocation());} catch (Exception e) {logger.error("上传失败", e);}}@GetMapping("/test2")public void createSignedUrlForStringGet2(@RequestParam("key") String key) {try {logger.info("文件下载的key=" + key);StopWatch stopWatch = new StopWatch();stopWatch.start();InputStream inputStream =null;OutputStream outputStream=null;try{inputStream=edsOssFileUploadService.downloadToEDS(key, "bucket01-test");stopWatch.stop();logger.info("文件下载执行时间(ms):" + stopWatch.getTotalTimeMillis());outputStream = new FileOutputStream("D:\\985.png");byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}catch (Exception e){logger.error("下载文件失败", e);}finally {if (outputStream!=null){outputStream.close();}if (inputStream!=null){inputStream.close();}}} catch (Exception e) {logger.error("文件下载", e);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/51578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统之部署记忆配对网页小游戏

Linux系统之部署记忆配对网页小游戏 一、小游戏介绍1.1 小游戏简介1.2 项目预览二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍三、检查本地环境3.1 检查系统版本3.2 检查系统内核版本3.3 检查软件源四、安装Apache24.1 安装Apache2软件4.2 启动apache2服务4.3 查看apache2…

redis cluster forget

项目场景&#xff1a; redis cluster有一台slave挂掉了&#xff0c;并且不准备在启用&#xff0c;但是使用cluster nodes命令时&#xff0c;还会有handshake出现&#xff0c;该怎么把他去掉 问题描述 以下是一个 Bash 脚本&#xff0c;可以自动化 Redis 集群的节点移除过程。…

【中项第三版】系统集成项目管理工程师 | 第 11 章 规划过程组⑥ | 11.15 - 11.17

前言 第11章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于10大管理的内容&#xff0c;学习要以教材为准。本章上午题分值预计在15分。 目录 11.15 规划资源管理 11.15.1 主要输入 11.15.2 主要工具与技术 11.15.3 主要输出 11.16 估算活动资源 11.1…

向有结果的人学习

有个朋友问我&#xff1a;我向有结果的人学习了&#xff0c;为何没有拿到结果&#xff1f;我觉得这个问题比较有代表性&#xff0c;决定写篇文章说说自己的看法。 现在比较流行一句话&#xff1a;向有结果的人学习。这句话本身没毛病&#xff0c;向有结果的人学习那是一定的&am…

Animate基本概念:补间动画

补间动画是Animate软件中比较重要的组成部分。 举例来说&#xff0c;假设第 1 帧和第 20 帧是属性关键帧&#xff0c;可以将舞台左侧的一个元件放在第 1 帧中&#xff0c;然后将其移至舞台右侧的第 20 帧中。在创建补间时&#xff0c;Animate 将计算影片剪辑在此中间的所有位置…

AI驱动的个性化招聘策略:重塑人才选拔的未来

一、引言 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已渗透到各行各业&#xff0c;为企业带来了前所未有的变革。在人力资源管理领域&#xff0c;AI的应用同样不容忽视。特别是在招聘环节&#xff0c;AI技术的引入不仅提高了效率&#xff0c;更通过数据…

coreDNS

1.概述 coreDNS的作用主要是作为DNS服务器&#xff0c;在集群内提供服务发现功能&#xff0c;也就是服务之间的互相定位的过程。他监听集群中service和pod的创建和销毁事件&#xff0c;当serivice或者pod被创建时&#xff0c;记录对应的解析记录。当其他pod通过域名来访问集群中…

css实现线条中间高亮,左右两边模糊(linear-gradient的运用)

效果&#xff1a; <div class"line"></div> .line {height: 1px;background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #a9c2ff 50%, rgba(255, 255, 255, 0) 100%);border-radius: 4px 4px 4px 4px; } CSS实现边框底部渐变色的方法:(最简单…

如何开发属于自己直播平台的主播美颜SDK?

本篇文章&#xff0c;笔者将从需求分析、技术选型、开发流程等方面进行详细讲解。 一、需求分析 在开发美颜SDK之前&#xff0c;首先需要进行详细的需求分析。主要包括以下几个方面&#xff1a; 1.美颜功能的具体需求&#xff1a;确定美颜效果&#xff0c;包括磨皮、美白、瘦…

EEPROM的最小擦除单元居然不是字节,而是页!

如果EEPROM的最小擦除单位是字节&#xff0c;那为什么还不能跨页写&#xff1f; 实际上&#xff0c;EEPROM的擦除操作通常是按页面进行的&#xff0c;而不是按字节进行的。虽然EEPROM支持按字节进行编程操作&#xff08;1->0&#xff09;&#xff0c;但擦除操作&#xff08…

Unity横板动作游戏 -为什么我又开始学习Unity,而不是Godot。

Readme 最近开始学习Unity制作2D动作游戏&#xff0c;由于一些操作第一次接触&#xff0c;为了加深印象&#xff0c;准备写这样一篇同步教程的笔记。 之前也接触过Unity&#xff0c;用 Unity 制作过一个非常简单的小游戏 Flappy Bird&#xff0c;并且魔改成了泰拉瑞亚的版本。…

Go语言实战:基于Go1.19的站点模板爬虫技术解析与应用

一、引言 1.1 爬虫技术的背景与意义 在互联网高速发展的时代&#xff0c;数据已经成为新的石油&#xff0c;而爬虫技术则是获取这种“石油”的重要工具。爬虫&#xff0c;又称网络蜘蛛、网络机器人&#xff0c;是一种自动化获取网络上信息的程序。它广泛应用于搜索引擎、数据分…

docker安装与container基本使用

安装 Homebrew 的 Cask 已经支持 Docker for Mac, mac用户狂喜 brew install --cask --appdir/Applications docker其他入门用法可参考 Docker Hello World- 菜鸟教程 或网上自行搜索博客学习。本文主要记录我运行go-zero-mall用到的一些注意点。当然&#xff0c;gonivinck项…

【深度学习】语音,Mel频谱图的前世今生

Mel频谱图的前世今生 背景与基本概念 Mel频谱图是音频信号处理中的一种表示形式&#xff0c;用于将音频信号转换为二维图像&#xff0c;这种表示形式在语音识别、语音合成和音频分类等领域中广泛应用。要理解Mel频谱图&#xff0c;首先需要了解以下几个基本概念&#xff1a; …

隆尧县“隆品佳尧”区域公用品牌发布推介会暨地标之都七月选品会成功举办

在国家乡村振兴战略与农业现代化建设的大背景下&#xff0c;隆尧县凭借其得天独厚的地理优势和丰富的自然资源&#xff0c;正在成为区域经济与品牌建设的一颗新星。为了进一步推动隆尧县的农业发展和乡村建设&#xff0c;由隆尧县商务局指导、隆尧县电子商务公共服务中心主办的…

在线医疗系统2024()

下载在最后 技术栈: ssmmysqljsp 展示: 下载地址: CSDN现在上传有问题,有兴趣的朋友先收藏.正常了贴上下载地址 备注:

计算机基础(day1)

1.什么是内存泄漏&#xff1f;什么是内存溢出&#xff1f;二者有什么区别&#xff1f; 2.了解的操作系统有哪些&#xff1f; Windows&#xff0c;Unix&#xff0c;Linux&#xff0c;Mac 3. 什么是局域网&#xff0c;广域网&#xff1f; 4.10M 兆宽带是什么意思&#xff1f;理论…

“等保测评:企业如何构建全面的信息安全管理体系“

随着信息技术的快速发展&#xff0c;企业面临的信息安全威胁日益严峻&#xff0c;信息安全管理体系的构建成为企业保障数据安全、维护业务连续性的关键。本文将围绕“等保测评&#xff1a;企业如何构建全面的信息安全管理体系”这一主题&#xff0c;从以下几个方面展开讨论&…

2024年阿里最新软件测试面试题:Web 测试+接口测试+App 测试

又到了一年一度的金九银十&#xff0c;互联网行业竞争是一年比一年严峻&#xff0c;作为软件测试工程师的我们唯有不停的学习&#xff0c;不断提升自己才能保证自己的核心竞争力从而拿到更好的薪水&#xff0c;进入心仪的企业&#xff08;阿里&#xff0c;字节跳动&#xff0c;…

第三方支付平台接口通道有什么优势及弊端?

目前&#xff0c;第三方支付是指支付机构通过互联网向用户提供在线支付服务。主要有两种支付方式&#xff1a;预付卡和信用卡支付。预付卡是指通过银行卡接受支付业务的银行卡。信用卡支付是指通过信用卡&#xff08;包括在线支付&#xff09;使用银行卡、手机通过POS等方式实现…