All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.cloudscope.service.impl.AliyunOSSWorker Maven / Gradle / Ivy

package cn.cloudscope.service.impl;

import cn.cloudscope.bean.DocumentReturnCodeEnum;
import cn.cloudscope.bean.DocumentUrlResult;
import cn.cloudscope.bean.YKUPResult;
import cn.cloudscope.config.OssConfiguration;
import cn.cloudscope.config.properties.OssProperties;
import cn.cloudscope.service.StorageWorker;
import cn.cloudscope.utils.DateUtil;
import cn.cloudscope.utils.FileUtil;
import cn.cloudscope.utils.ImageUtil;
import cn.cloudscope.utils.PathUtil;
import cn.cloudscope.utils.UUIDUtil;
import cn.cloudscope.utils.VideoUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CopyObjectRequest;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Date;
import java.util.List;

/**
 * @author wkp
 */
@Data
@Slf4j
@ConditionalOnBean(OssConfiguration.class)
public class AliyunOSSWorker implements StorageWorker {

    private OSSClient ossClient;
    private OssProperties ossProperties;

    public AliyunOSSWorker(OSSClient ossClient, OssProperties ossProperties) {
        this.ossClient = ossClient;
        this.ossProperties = ossProperties;
    }

    /**
     * 上传文件
     *
     * @param inputStream 文件流
     * @param fileName    文件名
     * @param folder      目标文件夹
     * @param thumbnail
     * @return 文件上传后的路径
     * @author wenxiaopeng
     **/
    @Override
    public YKUPResult upload(InputStream inputStream, String fileName, String folder, boolean thumbnail) {
        File file = new File(UUIDUtil.buildUuid() + "." + FileUtil.getFileSuffix(fileName));
        try {
            if (inputStream.available() <= 0) {
                throw new RuntimeException(DocumentReturnCodeEnum.DOCUMENT_EMPTY.getMsg());
            }
            file.createNewFile();
            IOUtils.copyLarge(inputStream, Files.newOutputStream(file.toPath()));
            String path;
            if (StringUtils.isNotBlank(folder)) {
                path = folder.endsWith("/") ? (folder + fileName) : (folder + "/" + fileName);
            } else {
                path = this.generatePath(fileName);
            }
            this.putObjectCommonFunction(Files.newInputStream(file.toPath()), path);
            YKUPResult result = YKUPResult.createResult(path, fileName);
            if (thumbnail) {
                try {
                    String suffix = FileUtil.getFileSuffix(file.getName());
                    if (ImageUtil.isImage(file)) {
                        InputStream thumbnailStream = ImageUtil.buildThumbnail(new FileInputStream(file), suffix);
                        this.putObjectCommonFunction(thumbnailStream, ImageUtil.appendSuffixHyphenThumbnail(path));
                    } else {
                        if (VideoUtil.isVideo(file)) {
                            InputStream frameStream = VideoUtil.captureFrame(file, 20);
                            String framePath = StringUtils.substringBeforeLast(path, ".") + ".jpg";
                            if (null != frameStream) {
                                this.putObjectCommonFunction(frameStream, framePath);
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("无法生成缩略图: {}", e.getMessage());
                }
            }
            return result;
        } catch (Exception e) {
            log.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
            throw new RuntimeException(DocumentReturnCodeEnum.SERVER_UNAVAILABLE.getMsg());
        }
    }

    @Override
    public YKUPResult upload(File file, String folder) {
        return StorageWorker.super.upload(file, folder);
    }

    @Override
    public String doUpload(InputStream stream, String path, String originName) {
        try {
            if (null == stream) {
                return null;
            }
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(stream.available());
            metadata.setCacheControl("no-cache");
            metadata.setHeader("Pragma", "no-cache");
            metadata.setContentEncoding("utf-8");
            metadata.setContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType());
            if (StringUtils.isNotBlank(originName)) {
                metadata.setContentDisposition("attachment;filename=" + originName);
            }
            PutObjectResult putObjectResult = ossClient.putObject(ossProperties.getBucketName(), path, stream, metadata);
            log.info("文件上传完成: {}, {}, {}", putObjectResult.getETag());
        } catch (Exception e) {
            log.error("上传失败:" + e, e);
            throw new RuntimeException(DocumentReturnCodeEnum.SERVER_UNAVAILABLE.getMsg());
        } finally {
            IOUtils.closeQuietly(stream);
        }
        return null;
    }

    @Override
    public YKUPResult upload(String filePath, String folder) {
        return StorageWorker.super.upload(filePath, folder);
    }

    /**
     * 下载文件
     *
     * @param key
     * @param response
     * @return java.io.InputStream
     * @author wangkp
     * @date 13:28 2022/1/25
     * [key, response]
     */
    @Override
    public void download(String key, OutputStream response) {
        if (!ossClient.doesObjectExist(ossProperties.getBucketName(), key)) {
            throw new RuntimeException("target file not found...");
        }
        try {
            OSSObject ossObject = ossClient.getObject(ossProperties.getBucketName(), key);
            if (ossObject != null) {
                InputStream inputStream = ossObject.getObjectContent();
                int buffer = 1024 * 10;
                byte[] data = new byte[buffer];
                try {
                    int read;
                    while ((read = inputStream.read(data)) != -1) {
                        response.write(data, 0, read);
                    }
                    response.flush();
                    response.close();
                    ossObject.close();
                } catch (IOException e) {
                    log.error("error info ", e);
                }
            }
        } catch (Exception e) {
            log.error("下载失败", e);
            throw new RuntimeException(DocumentReturnCodeEnum.SERVER_UNAVAILABLE.getMsg());
        }
    }

    @Override
    public String backupFile(String originPath, boolean deleteOrigin) {
        try {
            String destinationKey = appendSuffix(originPath, SUFFIX_BACKUP);
            String sourceBucketName = ossProperties.getBucketName();
            String destinationBucketName = ossProperties.getBucketName();
            CopyObjectResult copyObjectResult = ossClient.copyObject(new CopyObjectRequest(sourceBucketName, originPath,
                    destinationBucketName, destinationKey));
            if (null != copyObjectResult) {
                if (deleteOrigin) {
                    this.deleteFile(originPath);
                }
                return copyObjectResult.getETag();
            }
            return null;
        } catch (Exception e) {
            log.error("OSS复制失败" + e, e);
            throw new RuntimeException(DocumentReturnCodeEnum.BACKUP_FAILED.getMsg());
        }
    }


    /**
     * Description:根据路径删除文件
     * <>
     *
     * @param path 1
     * @return boolean
     * @author songcx
     * @date 14:31 2021/2/2
     **/
    @Override
    public boolean deleteFile(String path) {
        ossClient.deleteObject(ossProperties.getBucketName(), path);
        return true;
    }

    /**
     * 生成一个路径
     *
     * @param fileName 1
     * @return java.lang.String
     * @author wenxiaopeng
     * @date 2021/07/09 11:24
     **/
    private String generatePath(String fileName) {
        return DateUtil.format(new Date(), DateUtil.DateStyle.YEARMONTHDAY) + "/" + PathUtil.generatePath(UUIDUtil.get32UUID()) + "/" + fileName;
    }


    /**
     * 下载文件
     *
     * @param key 文件路径
     * @return java.io.InputStream
     * @author wenxiaopeng
     * @date 2021/07/09 12:08
     **/
    @Override
    public InputStream download(String key) {
        if (!ossClient.doesObjectExist(ossProperties.getBucketName(), key)) {
            throw new RuntimeException(String.valueOf(HttpStatus.SC_NOT_FOUND));
        }
        OSSObject ossObject = ossClient.getObject(ossProperties.getBucketName(), key);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        if (ossObject != null) {
            try (InputStream inputStream = ossObject.getObjectContent()) {
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, length);
                }
            } catch (IOException e) {
                log.error("error info ", e);
            }finally {
                try {
                    ossObject.close();
                } catch (IOException e) {
                    log.error("error info ", e);
                }
            }
            return new ByteArrayInputStream(outputStream.toByteArray());
        }
        return null;
    }


    /**
     * 获取一个可访问的文件链接
     *
     * @param key       文件路径
     * @param expiresIn 过期时间(秒),默认7天
     * @return DocumentUrlResult
     * @author wenxiaopeng
     * @date 2021/07/09 12:11
     **/
    @Override
    public DocumentUrlResult getDocumentUrl(String key, int expiresIn) {
        if (ObjectUtils.isEmpty(key)) {
            return null;
        }
        try {
            Date expires = new Date(System.currentTimeMillis() + expiresIn * 1000L);
            String url = ossClient.generatePresignedUrl(ossProperties.getBucketName(), key, expires).toString();
            DocumentUrlResult result = DocumentUrlResult.builder()
                    .expiresIn(expiresIn)
                    .url(url)
                    .build();
            try {
                if (ImageUtil.isImage(key)) {
                    String thumbnailPath = ossClient.generatePresignedUrl(ossProperties.getBucketName(), key, expires).toString();
                    result.setThumbnail(thumbnailPath);
                }
            } catch (Exception e) {
                log.error("generate thumbnail error: {}", e.getMessage());
            }
            return result;
        } catch (Exception e) {
            log.error("下载失败", e);
            throw new RuntimeException(DocumentReturnCodeEnum.SERVER_UNAVAILABLE.getMsg());
        }
    }

    /**
     * 多文件上传
     *
     * @param files 需要上传的文件位置
     * @return 上传的结果: 文件路径和文件真实名称(带后缀名)
     * @author wupanhua
     */
    @Override
    public YKUPResult uploadMultipleFile(List files) {
        try {
            if (files == null || files.size() <= 0) {
                throw new RuntimeException(DocumentReturnCodeEnum.DOCUMENT_EMPTY.getMsg());
            }
            for (File file : files) {
                this.upload(file);
            }
            return null;
        } catch (Exception e) {
            log.error("多文件上传失败" + e, e);
            throw new RuntimeException(DocumentReturnCodeEnum.SERVER_UNAVAILABLE.getMsg());
        }
    }

    /**
     * Description:
     * <创建一个指定有效期的数据访问链接>
     *
     * @param path   oss存储路径
     * @param expire 有效时间(s)
     * @return void
     * @throws Exception 文件创建异常
     * @author wupanhua
     * @date 11:30 2020-03-03
     */
    @Override
    public String crateFileExpireUrl(String path, int expire) {
        Date expiresIn = new Date(System.currentTimeMillis() + (expire * 1000L));
        String url = ossClient.generatePresignedUrl(ossProperties.getBucketName(), path, expiresIn).toString();
        return url;
    }

    /**
     * Description:
     * <创建一个指定有效期的图片访问链接>
     *
     * @param path   oss存储路径
     * @param expire 有效时间(s)
     * @return void
     * @author wupanhua
     * @date 11:30 2020-03-03
     */
    @Override
    public YKUPResult createImgExpireUrl(String path, int expire) {
        String originalImgUrl = this.crateFileExpireUrl(path, expire);
        String hyphenThumbnail = appendSuffix(path, SUFFIX_THUMBNAIL);
        String thumbnailUrl = this.crateFileExpireUrl(hyphenThumbnail, expire);
        return YKUPResult.createThumbnailResult(originalImgUrl, thumbnailUrl);
    }


    private void putObjectCommonFunction(InputStream inputStream, String path) throws IOException {
        //创建上传Object的Metadata
        ObjectMetadata metadata = new ObjectMetadata();
        //上传的文件的长度
        metadata.setContentLength(inputStream.available());
        //指定该Object被下载时的网页的缓存行为
        metadata.setCacheControl("no-cache");
        //指定该Object下设置Header
        metadata.setHeader("Pragma", "no-cache");
        //指定该Object被下载时的内容编码格式
        metadata.setContentEncoding("utf-8");
        //文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,
        //如果没有扩展名则填默认值application/octet-stream
        metadata.setContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType());
        ossClient.putObject(ossProperties.getBucketName(), path, inputStream, metadata);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy