1.S3Util  (springboot)
2 S3Util  (非 springboot)
 

 

 

 

依赖: 

<amazonaws.version>1.11.272</amazonaws.version>
  
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
         <dependency>
         <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>${amazonaws.version}</version>
        </dependency>    

 

 

 

S3Util  (springboot)
import com.amazonaws.*;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.InstanceProfileCredentialsProvider;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.regions.Regions;
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.util.AwsHostNameUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Future;
/***************************
 *<pre>
 * @Project Name : sea-file-service
 * @Package      : com.icil.bx
 * @File Name    : S3Util
 * @Author       : Sea
 * @Mail         : sealiu@icil.net
 * @Date         : 2023/5/18 12:25
 * @Purpose      :
 * @History      :
 *</pre>
 ***************************/
@Slf4j
@Component
public class S3Util   implements InitializingBean {

    /**
     * AWS_ACCESS_KEY=paZRwWpsuM3vkUuw
     * AWS_SECRET_KEY=WzLqVt5g9mtM33cQJyQApLOUivXahYeL
     * BUCKET_NAME=my-bucket
     * S3_ENDPOINT_URL=http://192.168.18.199:9001
     */
    @Value("${AWS_ACCESS_KEY}")
    private  String AWS_ACCESS_KEY ;
    @Value("${AWS_SECRET_KEY}")
    private  String AWS_SECRET_KEY ;
    @Value("${BUCKET_NAME}")
    private  String BUCKET_NAME ;
    @Value("${S3_ENDPOINT_URL:no}")
    private  String S3_ENDPOINT_URL;

    public static AmazonS3 s3Client;
    public static TransferManager transferManager;

    @Override
    public void afterPropertiesSet() throws Exception {
        initS3Client();
    }


    /**
     * 默认上传后,返回  bucket + /  + path
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static  class  FileNameTO{
        public String  path;
        public String  bucket;
    }

    /**
     * 默认上传后,返回  bucket + /  + path
     * @param fileName
     * @return
     */
    private static FileNameTO  parseFileName(String fileName){
        if(fileName.contains("/")){
            int index = fileName.indexOf("/");
            fileName = fileName.trim();
            String bucket = fileName.substring(0, index);
            String path = fileName.substring(index + 1);
            System.err.println("bucket " + bucket );
            System.err.println("path  " + path );
            return new FileNameTO(path,bucket);
        }
        return new FileNameTO();
    }



    /**
     * S3初始化
     */
    public  AmazonS3 initS3Client() {
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard()
                ////设置S3的地区
                .withRegion(Regions.AP_SOUTHEAST_1)
                .withCredentials(new InstanceProfileCredentialsProvider(false))
                .withClientConfiguration(new ClientConfiguration().withProtocol(Protocol.HTTP));

        if((S3_ENDPOINT_URL+"").trim().equals("no")){
            S3_ENDPOINT_URL="";
        }
        if(StringUtils.isNotBlank(S3_ENDPOINT_URL)){
            System.err.println("S3_ENDPOINT_URL " + S3_ENDPOINT_URL);
            AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(S3_ENDPOINT_URL, AwsHostNameUtils.parseRegion(S3_ENDPOINT_URL, AmazonS3Client.S3_SERVICE_NAME));
            builder.withEndpointConfiguration(endpointConfiguration);
        }
        if(StringUtils.isNotBlank(AWS_ACCESS_KEY) && StringUtils.isNotBlank(AWS_SECRET_KEY)){
            AWSCredentials awsCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
            builder.withCredentials(new AWSStaticCredentialsProvider(awsCredentials));
        }

        s3Client = builder.build();
        TransferManagerBuilder transferManagerBuilder = TransferManagerBuilder.standard();
        transferManagerBuilder.setS3Client(s3Client);
        transferManager = transferManagerBuilder.build();
        return s3Client;
    }


    /**
     * @param bucketName
     * @return
     */
    public  Boolean  createBucket(String bucketName){
         s3Client.createBucket(new CreateBucketRequest(bucketName).withCannedAcl(CannedAccessControlList.PublicReadWrite));
         return true;
    }

    /**
     * 上传图片到S3
     * @param bucketName
     * @param file
     * @param filePath    bucketName: /filePath/xx.png
     * @param transferManager
     * @return
     */
    @Async
    public Future<String> uploadFileToBucketAsync(String bucketName, File file, String filePath, TransferManager transferManager) {
        String url = uploadFileToBucket(bucketName, file, filePath, transferManager);
        return new AsyncResult<String>(url);
    }

    /**
     * 上传图片到S3
     * @param file
     * @param filePath    bucketName/filePath/xx.png
     * @return
     */
    public String uploadFileToBucket(File file, String filePath){
        log.info("start upload file {} ",filePath);
       return   uploadFileToBucket(BUCKET_NAME,file,filePath,transferManager);
    }
    /**
     * 上传图片到S3
     * @param bucketName
     * @param file
     * @param filePath    bucketName/filePath/xx.png
     * @param transferManager
     * @return
     */
    public String uploadFileToBucket(String bucketName, File file, String filePath, TransferManager transferManager) {
        if (file.exists() == false) {
            log.error(" !!!  file not exists!");
            return "";
        }
        try {
            String month = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
            filePath =month +"/"+filePath;
            log.info("File name is {}", file.getName());
            PutObjectRequest putRequest = new PutObjectRequest(bucketName, filePath, file);//.withCannedAcl(CannedAccessControlList.PublicReadWrite);
            if(StringUtils.isNotBlank(S3_ENDPOINT_URL)){
                putRequest.withCannedAcl(CannedAccessControlList.PublicReadWrite);
            }
            Upload upload = transferManager.upload(putRequest);
            upload.waitForCompletion();
        } catch (Exception e)
        {
            log.error("upload file name : {} to  S3 error : {} ",file.getName() , e);
            throw new RuntimeException(e.getMessage());
        }
        log.info("Upload " + file.getName() + " completed");
//        return bucketName+"/"+filePath;
        return "/"+filePath;
    }



    /**
     * 上传图片到S3 , 默认的bucket
     * @param url  网上url
     * @param S3Directory   bucket/directory/xx.png
     * @throws Exception
     */
    public  String upload(String url, String S3Directory)  {
        String fileName = "";
        try {
                AmazonS3 amazonS3Client = s3Client;
                //将url转为MultipartFile对象
                MultipartFile file = urlToMultipartFile(url);
                //通过url获取图片名称
                fileName = getFileName(url);
                if (StringUtils.isNotEmpty(S3Directory)) {
                    fileName = S3Directory + "/" + fileName;
                }
                ObjectMetadata objectMetadata = new ObjectMetadata();
                objectMetadata.setContentType(file.getContentType());
                objectMetadata.setContentLength(file.getSize());
                //调用S3上传文件
                PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, fileName, file.getInputStream(), objectMetadata);
                if(StringUtils.isNotBlank(S3_ENDPOINT_URL)){
                    putObjectRequest.withCannedAcl(CannedAccessControlList.PublicReadWrite);
                }
                Upload upload = transferManager.upload(putObjectRequest);
//                return  BUCKET_NAME+"/"+fileName;
                return  "/"+fileName;
            }
            catch (Exception e){
                log.error("upload file name : {} to  S3 error : {} ",fileName , e);
                return null;
            }
    }


    /**
     * judge existence By fileName
     * @param fileName
     * @return
     */
    public  boolean judgeExistFile(String fileName){
        boolean exist = s3Client.doesObjectExist(BUCKET_NAME, fileName);
        log.info(" {} exist :  {}", fileName , exist);
        return exist;
    }

    /**
     *  根据fileName , 生成临时 URL
     * @param fileName
     * @return
     */
    public  String generatePreViewUrl(String fileName) {
        FileNameTO fileNameTO = parseFileName(fileName);
        URL url = null;
        try {
            java.util.Date expiration = new java.util.Date();
            long milliSeconds = expiration.getTime();
            // Add 2 hour for user to download label.
            milliSeconds +=  2 * 60 * 60 * 1000;
            expiration.setTime(milliSeconds);
            GeneratePresignedUrlRequest generatePresignedUrlRequest =
                    new GeneratePresignedUrlRequest(fileNameTO.getBucket(), fileNameTO.getPath());
            generatePresignedUrlRequest.setMethod(HttpMethod.GET);
            generatePresignedUrlRequest.setExpiration(expiration);
            url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
            log.info("Pre-Signed URL = " + url.toString());
        } catch (Exception exception) {
            log.error(" {} generatePreViewUrl Error Message: {}" ,fileName, exception.getMessage());
        }
        String urlStr="";
        if(url!=null){
//            urlStr = url.toString().replaceAll("http", "https");
        }
        return urlStr;
    }




    /**
     * 下载文件到本地
     * @param fileName   bucket /  filePath
     * @return
     * @throws Exception
     */
    public  boolean downLoadToLoc(String fileName, String outFilePath){
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;
        try {
            inputStream = download(fileName);
            if(inputStream==null){return false;}
            fileOutputStream = new FileOutputStream(outFilePath);
            IOUtils.copy(inputStream,fileOutputStream);
            return true;
            } catch (IOException e)
            {
                e.printStackTrace();
            } finally {
                if (fileOutputStream != null) {
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return false;
    }


    /**
     * down file by fileName
     * @param fileName    bucket /  filePath
     * @return InputStream
     */
    public static InputStream download(String fileName) {
        FileNameTO fileNameTO = parseFileName(fileName);
        InputStream stream = null;
        S3Object s3Object = null;
        try {
            s3Object = s3Client.getObject(new GetObjectRequest(fileNameTO.getBucket(), fileNameTO.getPath()));
            stream = s3Object.getObjectContent();
        } catch (AmazonServiceException ase) {
            if (ase.getStatusCode() == 404) {
                log.warn(fileName + " doesn`t exist in S3 server!");
            } else {
                log.error(" The Exception is {} " , ase);
            }
        } finally {
//            if (s3Object != null) {
//                try {
//                    s3Object.close();
//                } catch (IOException e) {
//                    log.info(e.getMessage(),e);
//                }
//            }
        }
        return stream;
    }




    /**
     * 获取文件列表
     *
     * @param limit
     * @param prefix
     * @return
     * @throws IOException
     */
    public  List<S3ObjectSummary> getFileListPaginator(Integer limit, String prefix) throws IOException {
        try {
            AmazonS3 amazonS3Client = s3Client;
            ListObjectsV2Request req = new ListObjectsV2Request()
                    .withBucketName(BUCKET_NAME).withMaxKeys(limit).withPrefix(prefix);
            ListObjectsV2Result result;
            result = amazonS3Client.listObjectsV2(req);
//            for (S3ObjectSummary objectSummary : result.getObjectSummaries()) {
//                System.out.printf(" - %s (size: %d)\n", objectSummary.getKey(), objectSummary.getSize());
//            }
            result.setTruncated(true);
            return result.getObjectSummaries();
        } catch (AmazonServiceException e) {
            // 已经打通S3但处理失败
            e.printStackTrace();
        } catch (SdkClientException e) {
            // 链接S3失败
            e.printStackTrace();
        }
        return null;
    }


    /**
     * url转MultipartFile
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static MultipartFile urlToMultipartFile(String url) throws Exception {
        File file = null;
        MultipartFile multipartFile = null;
        try {
            HttpURLConnection httpUrl = (HttpURLConnection) new URL(url).openConnection();
            httpUrl.connect();
            file = inputStreamToFile(httpUrl.getInputStream(), "template.png");
            multipartFile = fileToMultipartFile(file);
            httpUrl.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return multipartFile;
    }

    /**
     * inputStream 转 File
     *
     * @param ins
     * @param name
     * @return
     * @throws Exception
     */
    public static File inputStreamToFile(InputStream ins, String name) throws Exception {
        File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
        OutputStream os = new FileOutputStream(file);
        int bytesRead;
        int len = 8192;
        byte[] buffer = new byte[len];
        while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
        file.deleteOnExit();
        return file;
    }

    /**
     * file转multipartFile
     *
     * @param file
     * @return
     */
    public static MultipartFile fileToMultipartFile(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem(file.getName(), "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new CommonsMultipartFile(item);
    }


    /**
     * @param multipartFile
     * @return File
     */
    public static File transferToFile(MultipartFile multipartFile) {
        File file = null;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            String[] filename = originalFilename.split("\\.");
            file = File.createTempFile(filename[0], filename[1]);
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 获取图片名称
     * @param url
     * @return
     */
    public static String getFileName(String url) {
        String[] urlArr = (url + "").split("/");
        String fileName = urlArr.length>1 ? urlArr[urlArr.length-1]:url;
        return fileName;
    }


}

 

 

 

FileHistoryDO
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document("file_history")
@Builder
public class FileHistoryDO {

    /**
     * 用户的id
     */
    private String uid;
    /**
     * sha256hexq
     */
    private String sha256;
    private String name;
    private String ulr;
    private Long size;
/**  m(movie):  movie ".RMVB|.FLV|.MP4|.AVI|.3GP|.FLV|.F4V|.WMV|.MPEG|.NAVI|.ASF|.WMV|.MOV");
     v(voice): VOICE".MP3|.WAV|.AAC|.WMA|.OGG|.FLAC|.APE|.CD|.MIDI");
     p(pic):  PIC ".SVG|.BMP|.JPG|.PNG|.TIF|.GIF|.PCX|.TGA|.EXIF|.FPX|.PSD|.CDR|.PCD|.DXF|.UFO|.EPS|.AI|.RAW|.WMF|.WEBP|.AVIF|.APNG");
     d(doc):  TXT".TXT|.DOC|.DOCX|.PPT|.PPTX|.PDF|.XLSX|.XLS|.PROPERTIES|.CONF|.SH|.BASH|.JSON|.SQL"*/
    private String type;

    /**
     * 创建时间时间戳 : 精确到秒
     */
    private Long cts = System.currentTimeMillis()/1000;
    /**
     *  创建时间 (用于直观显示 查询)
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date ctt =  new Date();

    /**
     * 删除操作
     */
    @JsonIgnore
    private Boolean active = true;

    private String remark;
    /**
     * 操作人 user name
     */
    private String operator;

    /**
     * @param name
     * @param sha256
     * @param size
     * @param uid
     * @param uid
     */
    public FileHistoryDO(String name, String sha256, Long size, String uid, String operator) {
        this.uid = uid;
        this.sha256 = sha256;
        this.name = name;
        this.operator = operator;
        this.size = size;
    }
}
View Code
FileUploadS3Handler
import com.icil.bx.common.utils.MapUtils;
import com.icil.bx.common.utils.S3Util;
import com.icil.bx.entity.file.FileHistoryDO;
import com.icil.bx.service.FileHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @PACKAGE : com.sea.bx.handler
 * @Author :  Sea
 * @Date : 8/18/21 5:12 PM
 * @Desc :  https://www.xxxxfc/f/v202108/Tom_and_Jerry003.mp4
 **/
@Slf4j
@Component
public class FileUploadS3Handler {

    private static Pattern FILM_PATTERN = Pattern.compile(".RMVB|.FLV|.MP4|.AVI|.3GP|.FLV|.F4V|.WMV|.MPEG|.NAVI|.ASF|.WMV|.MOV");
    private static Pattern VOICE_PATTERN = Pattern.compile(".MP3|.WAV|.AAC|.WMA|.OGG|.FLAC|.APE|.CD|.MIDI");
    private static Pattern PICTURE_PATTERN = Pattern.compile(".SVG|.BMP|.JPG|.PNG|.TIF|.GIF|.PCX|.TGA|.EXIF|.FPX|.PSD|.CDR|.PCD|.DXF|.UFO|.EPS|.AI|.RAW|.WMF|.WEBP|.AVIF|.APNG");
    private static Pattern TXT_PATTERN = Pattern.compile(".TXT|.DOC|.DOCX|.PPT|.PPTX|.PDF|.XLSX|.XLS|.PROPERTIES|.CONF|.SH|.BASH|.JSON|.SQL");

    private static final String VOICE_FILE = "voice";
    private static final String PICTURE_FILE = "picture";
    private static final String FILM_FILE = "film";
    private static final String OTHER_FILE = "other";
    private static final String TXT_FILE = "txt";

    @Autowired
    private FileHistoryService fileHistoryService;

    @Autowired
    private S3Util s3Util;

    /**
     * @param multipartFile
     * @param operator
     * @param uid
     * @return 后期可以考虑添加一张表记录文件的MD5 ,如果存在就不用在上传了,直接响应
     * @throws Exception
     */
    public String uploadFileAndRecord(MultipartFile multipartFile,String operator, String uid) throws Exception {
        String originalFilename = multipartFile.getOriginalFilename() + "".replace("/", "");
        String sha256hex = DigestUtils.sha256Hex(multipartFile.getBytes());
        //减少长度
        sha256hex = DigestUtils.md5Hex(sha256hex);
        return  uploadFileAndRecord(multipartFile.getInputStream(),multipartFile.getSize(),originalFilename,sha256hex,operator,uid);
    }


    /**
     * @param inputStream
     * @param fileSize
     * @param fileName
     * @param fileSha256hex
     * @param operator
     * @param uid
     * @throws Exception
     */
    public String uploadFileAndRecord(InputStream inputStream, Long fileSize, String fileName, String fileSha256hex, String operator, String uid) throws Exception {
        log.info("file name {}  and size {} ", fileName, fileSize);
        String suffix = getSuffix(fileName);
        FileHistoryDO fileDO = new FileHistoryDO(fileName,fileSha256hex,fileSize, uid,operator);
        fileDO.setType(getFileType(suffix));
        String url = checkHasUploaded(fileDO);
        //之前未上传过
        if(url==null){
            url = s3Util.uploadFileToBucket(S3Util.inputStreamToFile(inputStream,fileName),fileSha256hex+suffix);
        }
        //save record
        fileHistoryService.saveOrUpdate(fileDO);
        return url;
    }



    /**
     * if uploaded  return url  else return null
     * @return
     */
    private String checkHasUploaded(FileHistoryDO file){
        List<FileHistoryDO> fileHistoryDOList = fileHistoryService.dynamicQuery(MapUtils.of("sha256", file.getSha256(), "size", file.getSize()), "cts", 2);
        if(fileHistoryDOList!=null&& fileHistoryDOList.size()>0){
            //如果存在, 保存一份记录
            FileHistoryDO fileDB = fileHistoryDOList.get(0);
            file.setType(fileDB.getType());
            file.setUlr(fileDB.getUlr());
            return fileDB.getUlr();
        }
        return null;
    }


    public static String getSuffix(String fileName) {
        try {
            fileName = fileName.replace("/", "");
            return fileName.substring(fileName.lastIndexOf("."));
        }catch (Exception e){
            log.warn("fileName  {} no suffix ",fileName);
            return "";
        }
    }


    public static String getFileType(String suffix) {
        //film
        if (FILM_PATTERN.matcher((suffix + "").toUpperCase()).find()) {
            return FILM_FILE;
        }
        //voice
        else if (VOICE_PATTERN.matcher((suffix + "").toUpperCase()).find()) {
            return VOICE_FILE;
        }
        //picture
        else if (PICTURE_PATTERN.matcher((suffix + "").toUpperCase()).find()) {
            return PICTURE_FILE;
        }
        //txt
        else if (TXT_PATTERN.matcher((suffix + "").toUpperCase()).find()) {
            return TXT_FILE;
        } else {
            //other file
            return OTHER_FILE;
        }
    }




}
View Code

 

 

 

S3Util  (非 springboot)
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.HttpMethod;
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.Upload;
import com.amazonaws.util.AwsHostNameUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.concurrent.Future;
/***************************
 *<pre>
 * @Project Name : sea-file-service
 * @Package      : com.sea.
 * @File Name    : S3Util
 * @Author       : Sea
 * @Mail         : lshan523@163.com
 * @Date         : 2023/5/18 12:25
 * @Purpose      :
 * @History      :
 *</pre>
 ***************************/
@Slf4j
public class S3Util {

    private static String AWS_ACCESS_KEY = "paZRwWpsuM3vkUuw";
    private static String AWS_SECRET_KEY = "WzLqVt5g9mtM33cQJyQApLOUivXahYeL";
    private static String BUCKET_NAME = "my-bucket";
    private static String S3_ENDPOINT_URL = "http://192.168.18.199:9001";


    public static AmazonS3 s3Client;
    public static TransferManager transferManager;
    static {
        initS3Client();
    }

    /**
     * 默认上传后,返回  bucket + /  + path
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static  class  FileNameTO{
        public String  path;
        public String  bucket;
    }

    /**
     * 默认上传后,返回  bucket + /  + path
     * @param fileName
     * @return
     */
    private static FileNameTO  parseFileName(String fileName){
        if(fileName.contains("/")){
            int index = fileName.indexOf("/");
            fileName = fileName.trim();
            String bucket = fileName.substring(0, index);
            String path = fileName.substring(index + 1);
            System.err.println("bucket " + bucket );
            System.err.println("path  " + path );
            return new FileNameTO(path,bucket);
        }
        return new FileNameTO();
    }
    /**
     * S3初始化
     */
    public static AmazonS3 initS3Client() {
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
        if(StringUtils.isNotBlank(S3_ENDPOINT_URL)){
            AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(S3_ENDPOINT_URL, AwsHostNameUtils.parseRegion(S3_ENDPOINT_URL, AmazonS3Client.S3_SERVICE_NAME));
            builder.withEndpointConfiguration(endpointConfiguration);
        }
        if(StringUtils.isNotBlank(AWS_ACCESS_KEY) && StringUtils.isNotBlank(AWS_SECRET_KEY)){
            AWSCredentials awsCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
            builder.withCredentials(new AWSStaticCredentialsProvider(awsCredentials));
        }
        //设置S3的地区
        //builder.setRegion(regionName);
        s3Client = builder.build();
        transferManager = new TransferManager(s3Client);
        return s3Client;
    }


/**
     * @param bucketName
     * @return
     */
    public  Boolean  createBucket(String bucketName){
         s3Client.createBucket(new CreateBucketRequest(bucketName).withCannedAcl(CannedAccessControlList.PublicReadWrite));
         return true;
    }


    /**
     * 上传图片到S3
     * @param bucketName
     * @param file
     * @param filePath    bucketName/filePath/xx.png
     * @param transferManager
     * @return
     */
    @Async
    public Future<String> uploadFileToBucketAsync(String bucketName, File file, String filePath, TransferManager transferManager) {
        String url = uploadFileToBucket(bucketName, file, filePath, transferManager);
        return new AsyncResult<String>(url);
    }

    /**
     * 上传图片到S3
     * @param bucketName
     * @param file
     * @param filePath    bucketName/filePath/xx.png
     * @param transferManager
     * @return
     */
    public String uploadFileToBucket(String bucketName, File file, String filePath, TransferManager transferManager) {
        if (file.exists() == false) {
            log.error(" !!!  file not exists!");
            return "";
        }
        try {
            log.info("File name is {}", file.getName());
            PutObjectRequest pOrequest = new PutObjectRequest(bucketName, filePath, file).withCannedAcl(CannedAccessControlList.PublicReadWrite);;
            Upload upload = transferManager.upload(pOrequest);
            upload.waitForCompletion();
        } catch (Exception e)
        {
            log.error("upload file name : {} to  S3 error : {} ",file.getName() , e);
        }
        log.info("Upload " + file.getName() + " completed");
        return bucketName+"/"+filePath;
    }



    /**
     * 上传图片到S3 , 默认的bucket
     * @param url  网上url
     * @param S3Directory   bucket/directory/xx.png
     * @throws Exception
     */
    public static String upload(String url, String S3Directory)  {
        String fileName = "";
        try {
                AmazonS3 amazonS3Client = s3Client;
                //将url转为MultipartFile对象
                MultipartFile file = urlToMultipartFile(url);
                //通过url获取图片名称
                fileName = getFileName(url);
                if (StringUtils.isNotEmpty(S3Directory)) {
                    fileName = S3Directory + "/" + fileName;
                }
                ObjectMetadata objectMetadata = new ObjectMetadata();
                objectMetadata.setContentType(file.getContentType());
                objectMetadata.setContentLength(file.getSize());
                //调用S3上传文件
                PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, fileName, file.getInputStream(), objectMetadata)
                        .withCannedAcl(CannedAccessControlList.PublicRead);
                Upload upload = transferManager.upload(putObjectRequest);
                return  BUCKET_NAME+"/"+fileName;
            }
            catch (Exception e){
                log.error("upload file name : {} to  S3 error : {} ",fileName , e);
                return null;
            }
    }


    /**
     * judge existence By fileName
     * @param fileName
     * @return
     */
    public static boolean judgeExistFile(String fileName){
        boolean exist = s3Client.doesObjectExist(BUCKET_NAME, fileName);
        log.info(" {} exist :  {}", fileName , exist);
        return exist;
    }

    /**
     *  根据fileName , 生成临时 URL
     * @param fileName
     * @return
     */
    public static String generatePreViewUrl(String fileName) {
        FileNameTO fileNameTO = parseFileName(fileName);
        URL url = null;
        try {
            java.util.Date expiration = new java.util.Date();
            long milliSeconds = expiration.getTime();
            // Add 2 hour for user to download label.
            milliSeconds +=  2 * 60 * 60 * 1000;
            expiration.setTime(milliSeconds);
            GeneratePresignedUrlRequest generatePresignedUrlRequest =
                    new GeneratePresignedUrlRequest(fileNameTO.getBucket(), fileNameTO.getPath());
            generatePresignedUrlRequest.setMethod(HttpMethod.GET);
            generatePresignedUrlRequest.setExpiration(expiration);
            url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
            log.info("Pre-Signed URL = " + url.toString());
        } catch (Exception exception) {
            log.error(" {} generatePreViewUrl Error Message: {}" ,fileName, exception.getMessage());
        }
        String urlStr="";
        if(url!=null){
//            urlStr = url.toString().replaceAll("http", "https");
        }
        return urlStr;
    }




    /**
     * 下载文件到本地
     * @param fileName   bucket /  filePath
     * @return
     * @throws Exception
     */
    public static boolean downLoadToLoc(String fileName, String outFilePath){
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;
        try {
            inputStream = download(fileName);
            if(inputStream==null){return false;}
            fileOutputStream = new FileOutputStream(outFilePath);
            IOUtils.copy(inputStream,fileOutputStream);
            return true;
            } catch (IOException e)
            {
                e.printStackTrace();
            } finally {
                if (fileOutputStream != null) {
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return false;
    }


    /**
     * down file by fileName
     * @param fileName    bucket /  filePath
     * @return InputStream
     */
    public static InputStream download(String fileName) {
        FileNameTO fileNameTO = parseFileName(fileName);
        InputStream stream = null;
        S3Object s3Object = null;
        try {
            s3Object = s3Client.getObject(new GetObjectRequest(fileNameTO.getBucket(), fileNameTO.getPath()));
            stream = s3Object.getObjectContent();
        } catch (AmazonServiceException ase) {
            if (ase.getStatusCode() == 404) {
                log.warn(fileName + " doesn`t exist in S3 server!");
            } else {
                log.error(" The Exception is {} " , ase);
            }
        } finally {
//            if (s3Object != null) {
//                try {
//                    s3Object.close();
//                } catch (IOException e) {
//                    log.info(e.getMessage(),e);
//                }
//            }
        }
        return stream;
    }




    /**
     * 获取文件列表
     *
     * @param limit
     * @param prefix
     * @return
     * @throws IOException
     */
    public static List<S3ObjectSummary> getFileListPaginator(Integer limit, String prefix) throws IOException {
        try {
            AmazonS3 amazonS3Client = s3Client;
            ListObjectsV2Request req = new ListObjectsV2Request()
                    .withBucketName(BUCKET_NAME).withMaxKeys(limit).withPrefix(prefix);
            ListObjectsV2Result result;
            result = amazonS3Client.listObjectsV2(req);
//            for (S3ObjectSummary objectSummary : result.getObjectSummaries()) {
//                System.out.printf(" - %s (size: %d)\n", objectSummary.getKey(), objectSummary.getSize());
//            }
            result.setTruncated(true);
            return result.getObjectSummaries();
        } catch (AmazonServiceException e) {
            // 已经打通S3但处理失败
            e.printStackTrace();
        } catch (SdkClientException e) {
            // 链接S3失败
            e.printStackTrace();
        }
        return null;
    }


    /**
     * url转MultipartFile
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static MultipartFile urlToMultipartFile(String url) throws Exception {
        File file = null;
        MultipartFile multipartFile = null;
        try {
            HttpURLConnection httpUrl = (HttpURLConnection) new URL(url).openConnection();
            httpUrl.connect();
            file = inputStreamToFile(httpUrl.getInputStream(), "template.png");
            multipartFile = fileToMultipartFile(file);
            httpUrl.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return multipartFile;
    }

    /**
     * inputStream 转 File
     *
     * @param ins
     * @param name
     * @return
     * @throws Exception
     */
    public static File inputStreamToFile(InputStream ins, String name) throws Exception {
        File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
        OutputStream os = new FileOutputStream(file);
        int bytesRead;
        int len = 8192;
        byte[] buffer = new byte[len];
        while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
        return file;
    }

    /**
     * file转multipartFile
     *
     * @param file
     * @return
     */
    public static MultipartFile fileToMultipartFile(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem(file.getName(), "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new CommonsMultipartFile(item);
    }



    /**
     * 获取图片名称
     * @param url
     * @return
     */
    public static String getFileName(String url) {
        String[] urlArr = (url + "").split("/");
        String fileName = urlArr.length>1 ? urlArr[urlArr.length-1]:url;
        return fileName;
    }


}

 

posted on 2023-05-18 17:12  lshan  阅读(201)  评论(0编辑  收藏  举报