Spring Cloud微服务集成 AWS S3 实战上传文件夹

这是第一次针对文件以及对象存储的使用,写个案例,设计如有不妥之处,多多指教

首先,我们引入依赖包

		
		<dependency>
            <groupId>com.amazonawsgroupId>
            <artifactId>aws-java-sdkartifactId>
            <version>1.11.136version>
        dependency>

        
        <dependency>
            <groupId>com.github.junrargroupId>
            <artifactId>junrarartifactId>
            <version>4.0.0version>
        dependency>

S3工具

import com.amazonaws.ClientConfigurationFactory;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.*;;
import com.amazonaws.services.s3.*;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.services.s3.transfer.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.List;

/**
 * @ClassName S3AutoConfiguration
 * @Desc S3配置
 * @Author Fyf
 * @Date 2020/3/13 9:29
 * @Version 1.0
 **/
@Lazy
@Component
public class S3Util {

    AmazonS3 s3;

    TransferManager tm;

    String bucketName; // 你 bucket 的名字 首先需要保证 s3 上已经存在该存储桶

    public S3Util() {
        this.s3 = new AmazonS3Client(new BasicAWSCredentials("access_key", "secret_key")
                , new ClientConfigurationFactory().getConfig().withSocketTimeout(31000));

        s3.setRegion(Region.getRegion(Regions.US_EAST_2));
        tm = new TransferManager(s3);
        this.bucketName = "ezblock";
    }

    public String upload(String fileName, InputStream fileStream, ObjectMetadata objectMetadata) {
        s3.putObject(new PutObjectRequest(bucketName, fileName, fileStream, objectMetadata)
                .withCannedAcl(CannedAccessControlList.PublicRead));
        GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucketName, fileName);
        URL url = s3.generatePresignedUrl(urlRequest);
        return String.valueOf(url);
    }

    /**
     * @param filePath 文件夹名称
     * @param file     要上传的文件
     * @description:
     * @author: Fyf
     * @time: 2020/3/16 10:16
     * @return:
     */
    public void uploadFile(String filePath, String fileName, File file) {
        s3.putObject(new PutObjectRequest(bucketName + "/" + filePath, fileName, file)
                .withCannedAcl(CannedAccessControlList.PublicRead));
    }

    /**
     * @param dirName 新建文集夹名称 / 唯一标识
     * @param directory 本地文件夹路径
     * @description: 上传文件夹(异步)
     * @author: Fyf
     * @time: 2020/3/17 11:15
     */
    public MultipleFileUpload uploadDir(String dirName, File directory) {
        boolean includeSubdirectoryies = true;
        MultipleFileUpload upload = tm.uploadDirectory(bucketName, dirName, directory, includeSubdirectoryies);
        return upload;
    }
    
}

业务实现

	@Transactional
    @PostMapping(value="/product",consumes = "multipart/form-data")
    public Object uploadProduct(@RequestParam("name") String name,
                                @RequestParam("type") String type,
                                @RequestPart("file") MultipartFile file) throws IOException {
        File destDir = null;
        Archive archive = null;
        try {
            archive = new Archive(file.getInputStream());
            // 生成唯一标识
            String dirName  =TokenUtil.createToken();
            destDir = new File( System.getProperties().getProperty("user.home")+ File.separator +dirName);
            FileOutputStream fos = null;
            FileHeader fileHeader = archive.nextFileHeader();
            File destFileName = null;
            // 解压文件写入到本地
            while (fileHeader != null) {
                String compressFileName = fileHeader.getFileNameString().trim();
                destFileName = new File(destDir.getAbsolutePath() + "/" + compressFileName);
                if (fileHeader.isDirectory()) {
                    if (!destFileName.exists()) {
                        destFileName.mkdirs();
                    }
                    fileHeader = archive.nextFileHeader();
                    continue;
                }
                if (!destFileName.getParentFile().exists()) {
                    destFileName.getParentFile().mkdirs();
                }
                fos = new FileOutputStream(destFileName);
                archive.extractFile(fileHeader, fos);
                fos.close();
                fileHeader = archive.nextFileHeader();
            }
            // upload to s3 
            MultipleFileUpload upload = s3.uploadDir(dirName , destDir);
            // 等待上传完成(阻塞) 这是为了防止异步上传时,我们在接口最后删除了文件夹,导致删除失败
            upload.waitForCompletion();
            // 生成数据
            int iret = productMapper.insert(new EzblockProduct(0,name,type,"",dirName,String.valueOf(System.currentTimeMillis())));
            return ResponseUtil.checkSucessful(iret,"上传产品失败");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.produce("V1","Product", ExceptionLogUtils.logMessage(e,this.getClass()));
            return ResponseUtil.failure(CodeStatus.FAIL,"上传产品失败");
        }finally {
            if (archive!=null){
                archive.close();
            }
            if (destDir!=null){
                // 删除生成的文件夹
                FileUtil.deleteAllFilesOfDir(destDir);
            }
        }
    }

服务消费者

Feign 服务内部调用

@FeignClient(value = "provider-member")
@RequestMapping("/api/web/v2")
public interface ProductClient {

    @PostMapping(value="/product",consumes = "multipart/form-data")
    Object uploadProduct(@RequestParam("name") String name,
                                @RequestParam("type") String type,
                                @RequestPart("file") MultipartFile file);
}

对外开放接口实现

@RestController
public class ProductController {
		
	@Autowired
    ProductClient productClient;

    /**
     * @description: 上传产品 包含文件
     * @author: Fyf
     * @time: 2020/3/16 17:54
     * @return:
     */
    @PostMapping("/upload/product")
    public Object upload(@RequestParam("name") String name,
                         @RequestParam("type") String type,
                         @RequestParam("file") MultipartFile file){
        return productClient.uploadProduct(name,type,file);
    }

}

接口实现后测试,解压后100MB左右的文件夹,整体耗时50s左右
Spring Cloud微服务集成 AWS S3 实战上传文件夹_第1张图片
下面是 S3 管理控制台
Spring Cloud微服务集成 AWS S3 实战上传文件夹_第2张图片

你可能感兴趣的:(Spring,Cloud微服务,其他,java,aws)