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);}}