目录

官方地址

COS对象存储

COS-demo-Github

依赖引入

		<!-- tencent COS -->
        <dependency>
            <groupId>com.qcloud</groupId>
            <artifactId>cos_api</artifactId>
            <version>5.6.54</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>com.tencentcloudapi</groupId>
            <artifactId>tencentcloud-sdk-java</artifactId>
            <!-- go to https://search.maven.org/search?q=tencentcloud-sdk-java and get the latest version. -->
            <!-- 请到https://search.maven.org/search?q=tencentcloud-sdk-java查询所有版本,最新版本如下 -->
            <version>3.1.322</version>
        </dependency>

        <!--xml解析工具 解析媒体数据-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

yml文件配置

#腾讯cos 存储
tencent:
  cos:
    secretId:  
    secretKey: 
    region: 
    baseUrl: 
    bucket: 

配置类

ConfigurationProperties(prefix = "tencent.cos")
@Component
public class TencentCosConfig {
    /**腾讯云的SecretId*/
    public static String secretId;
    /**腾讯云的SecretKey*/
    public static String secretKey;
    /**腾讯云的bucket (存储桶)*/
    public static String bucket;
    /**腾讯云的region(bucket所在地区)*/
    public static String region;
    /**腾讯云的allowPrefix(允许上传的路径)*/
    public static String allowPrefix = "*";
    /**腾讯云的临时密钥时长(单位秒)*/
    public static String durationSeconds;
    /**腾讯云的访问基础链接:*/
    public static String baseUrl;
    
    public void setSecretId(String secretId) {
        TencentCosConfig.secretId = secretId;
    }

    public void setSecretKey(String secretKey) {
        TencentCosConfig.secretKey = secretKey;
    }

    public void setBucket(String bucket) {
        TencentCosConfig.bucket = bucket;
    }

    public void setRegion(String region) {
        TencentCosConfig.region = region;
    }

    public void setAllowPrefix(String allowPrefix) {
        TencentCosConfig.allowPrefix = allowPrefix;
    }

    public void setDurationSeconds(String durationSeconds) {
        TencentCosConfig.durationSeconds = durationSeconds;
    }

    public void setBaseUrl(String baseUrl) {
        TencentCosConfig.baseUrl = baseUrl;
    }
}

实现

@Slf4j
public class TencentCosUtils {
    /**
     * 桶的名称
     */
    static String bucketName = TencentCosConfig.bucket;
    static COSCredentials cred ;
    static ClientConfig clientConfig ;
    static COSClient cosClient ;
    static Region region;

    static {
        // 1 初始化用户身份信息(secretId, secretKey)
        cred = new BasicCOSCredentials(TencentCosConfig.secretId, TencentCosConfig.secretKey);
        // 2 设置 bucket 的地域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        region = new Region(TencentCosConfig.region);
        clientConfig = new ClientConfig(region);
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 3 生成 cos 客户端。
        cosClient = new COSClient(cred, clientConfig);
    }

    /**
     * 初始化CosClient
     * @return client
     */
    public static COSClient initCosClient(){
        // 1 初始化用户身份信息(secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(TencentCosConfig.secretId, TencentCosConfig.secretKey);
        // 2 设置 bucket 的地域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        Region region = new Region(TencentCosConfig.region);
        ClientConfig clientConfig = new ClientConfig(region);
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 3 生成 cos 客户端。
        return new COSClient(cred, clientConfig);
    }

    /**
     * 上传
     * @param srcFilePath 源文件路径
     * @param targetFilePath 目标文件路径
     * @return 云访问路径
     */
    public static String upload(String srcFilePath, String targetFilePath){
        Assert.notNull(srcFilePath, "上传文件路径为空!");
        // 处理文件路径
        srcFilePath = srcFilePath.startsWith("/") ? srcFilePath : "/" + srcFilePath;
        targetFilePath = ObjectUtils.isEmpty(targetFilePath) ? FileUploadUtils.extractFilename(srcFilePath) : targetFilePath;
        targetFilePath = targetFilePath.startsWith("/") ? targetFilePath : "/" + targetFilePath;

        targetFilePath = addFilePre(targetFilePath);
        String result = null;
        try{
            // 指定要上传的文件
            File localFile = new File(srcFilePath);
            // 指定文件上传到 COS 上的路径,即对象键。例如对象键为folder/picture.jpg,则表示将文件 picture.jpg 上传到 folder 路径下
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, targetFilePath, localFile);
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
            log.info("腾讯上传文件成功:{}", putObjectResult.getETag());
            result = TencentCosConfig.baseUrl + targetFilePath;
        } catch (CosClientException e) {
            //失败,抛出 CosServiceException
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 字节流上传
     * @param file 文件
     * @param filePath 目标文件路径
     * @return 云访问路径
     */
    public static String upload(MultipartFile file, String filePath){
        Assert.notNull(file, "上传文件为空!");
        log.info("开始上传文件:" + filePath);
        // 处理文件路径
        filePath = ObjectUtils.isEmpty(filePath) ? FileUploadUtils.extractFilename(file) : filePath;
        filePath = filePath.startsWith("/") ? filePath : "/" + filePath;
        filePath = addFilePre(filePath);

        String resultUrl = null;
        try{
            byte[] bytes = file.getBytes();
            //文件大小 建议不超过2M
            int length = bytes.length;
            // 获取文件流
            InputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // 从输入流上传必须制定content length, 否则http客户端可能会缓存所有数据,存在内存OOM的情况
            objectMetadata.setContentLength(length);
            // 默认下载时根据cos路径key的后缀返回响应的contenttype, 上传时设置contenttype会覆盖默认值
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, byteArrayInputStream, objectMetadata);
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
            log.info("腾讯上传文件成功:{}",putObjectResult.getETag());
            resultUrl = TencentCosConfig.baseUrl + filePath;
        } catch (CosClientException | IOException e) {
            //失败,抛出 CosServiceException
            e.printStackTrace();
        }
        return resultUrl;
    }

    /**
     * 删除文件 自动判断文件是否存在
     * @param filePath 文件名
     */
    public static void delete(String filePath){
        Assert.notNull(filePath, "删除文件路径为空!");
        try {
            cosClient.deleteObject(bucketName, filePath);
            log.info("文件删除成功");
        } catch (CosClientException serverException) {
            serverException.printStackTrace();
        }
    }

    /**
     * 下载到指定文件
     * @param srcFilePath 源文件路径
     * @param targetFilePath 目标文件路径
     */
    public static void downloadSingle(String srcFilePath, String targetFilePath){
        Assert.notNull(srcFilePath, "下载源文件路径为空!");
        Assert.notNull(srcFilePath, "下载目标文件路径为空!");
        try{
            // 下载到指定的本地路径
            if(ObjectUtils.isEmpty(srcFilePath) || ObjectUtils.isEmpty(targetFilePath)) {
                throw new CustomException("下载路径为空");
            }
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, srcFilePath);
            ObjectMetadata downObjectMeta = cosClient.getObject(getObjectRequest, new File(targetFilePath));
        } catch (CosClientException serverException) {
            serverException.printStackTrace();
        }
    }

    /**
     * 下载文件流
     * @param filePath 文件路径
     */
    public static void downloadSingle(String filePath, HttpServletResponse response){
        String fileName = FileUtils.getName(filePath);
        try{
            COSObject cosObject = cosClient.getObject(bucketName, filePath);
            InputStream in = cosObject.getObjectContent();
            //设置文件名
            FileUtils.setAttachmentResponseHeader(response, fileName);

            //读取文件流
            ServletOutputStream outputStream = response.getOutputStream();
            IoUtils.copy(in, outputStream);
            outputStream.close();
            in.close();
        } catch (CosClientException | IOException serverException) {
            serverException.printStackTrace();
        }
    }

    /**
     * copyObject最大支持5G文件的copy
     *  支持跨桶 跨区域
     * @param reg 区域
     * @param srcBucketName 源bucket, bucket名需包含appid
     * @param srcKey 要拷贝的源文件路径
     * @param destBucketName 目的bucket, bucket名需包含appid
     * @param destKey 要拷贝的目的文件路径
     */
    public static void copySmallFile(String reg, String srcBucketName, String srcKey, String destBucketName, String destKey) {
        Region region = new Region(reg);
        CopyObjectRequest copyObjectRequest = new CopyObjectRequest(region, srcBucketName,
                srcKey, destBucketName, destKey);
        try {
            log.info("开始文件复制:源路径{},目的路径{}",srcKey, destKey);
            CopyObjectResult copyObjectResult = cosClient.copyObject(copyObjectRequest);
            log.info("完成文件复制:源路径{},目的路径{}",srcKey, destKey);
            //crc64 可以验证数据的完整性
            String crc64 = copyObjectResult.getCrc64Ecma();
        } catch (CosClientException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 获取媒体数据
     * @param filePath 文件路径
     * @return Media
     */
    public static MediaInfoVO getMetaInfo(String filePath){
        filePath = filePath.contains("com") ? filePath : TencentCosConfig.baseUrl + FileUtils.SLASH + filePath;
        String getUrl = filePath + "?ci-process=videoinfo";
        MediaInfoVO mediaInfoVO = new MediaInfoVO();
        try {
            //1·获取MediaInfo 主体数据
            JSONObject jsonObject = TencentApiUtils.doGet(getUrl);
            log.info("mediaInfo1{}",jsonObject.getJSONArray("MediaInfo").toJSONString());

            //2·获取format 数据
            Object formatObject = jsonObject.getJSONArray("MediaInfo").getJSONObject(0).
                    getJSONArray("Format").get(0);
            MediaFormatVO format = JSON.parseObject(JSONObject.toJSONString(formatObject), MediaFormatVO.class);
            //时长为0 格式不正确
            if(Objects.isNull(format.getDuration())){
                format.setDuration(-1f);
            }
            mediaInfoVO.setFormat(format);

            //3·获取stream 数据 目前不使用 详细流数据
            if(!Objects.isNull(formatObject)){
                return mediaInfoVO;
            }
            JSONObject streamJson = jsonObject.getJSONArray("MediaInfo")
                    .getJSONObject(0).getJSONArray("Stream").getJSONObject(0);
            MediaStreamVO stream = new MediaStreamVO();
            //视频
            Object videObject = streamJson.getJSONArray("Video");
            if(!Objects.isNull(videObject)){
                videObject = streamJson.getJSONArray("Video").get(0);
                stream.setVideo(JSON.parseObject(JSONObject.toJSONString(videObject), MediaVideoVO.class));
            }
            //音频
            Object audioObject = streamJson.getJSONArray("Audio");
            if(!Objects.isNull(audioObject)){
                audioObject = streamJson.getJSONArray("Audio").get(0);
                stream.setAudio(JSON.parseObject(JSONObject.toJSONString(audioObject), MediaAudioVO.class));
            }
            //字幕
            Object subtitleObject = streamJson.getJSONArray("Subtitle");
            if(!Objects.isNull(subtitleObject)){
                subtitleObject = streamJson.getJSONArray("Subtitle").get(0);
                stream.setSubtitle(JSON.parseObject(JSONObject.toJSONString(subtitleObject), MediaSubtitleVO.class));
            }
            mediaInfoVO.setStream(stream);
            log.info("mediaInfo{}}",JSONObject.toJSONString(mediaInfoVO));

        } catch (IOException e) {
            log.info("获取媒体数据错误{}", e.getMessage());
        }
        return mediaInfoVO;
    }
}

XML解析工具类

import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
 
public class StringAnalysisXml {
    /**
     * String 转 org.dom4j.Document
     * @param xml
     * @return
     * @throws DocumentException
     */
    public static Document strToDocument(String xml){
        try {
            //加上xml标签是为了获取最外层的标签,如果不需要可以去掉
            return DocumentHelper.parseText(xml);
        } catch (DocumentException e) {
            return null;
        }
    }
 
    /**
     * org.dom4j.Document 转  com.alibaba.fastjson.JSONObject
     * @param xml
     * @return
     * @throws DocumentException
     */
    public static JSONObject documentToJSONObject(String xml){
        return elementToJSONObject(strToDocument(xml).getRootElement());
    }
 
    /**
     * org.dom4j.Element 转  com.alibaba.fastjson.JSONObject
     * @param node
     * @return
     */
    public static JSONObject elementToJSONObject(Element node) {
        JSONObject result = new JSONObject();
        // 当前节点的名称、文本内容和属性
        List<Attribute> listAttr = node.attributes();// 当前节点的所有属性的list
        for (Attribute attr : listAttr) {// 遍历当前节点的所有属性
            result.put(attr.getName(), attr.getValue());
        }
        // 递归遍历当前节点所有的子节点
        List<Element> listElement = node.elements();// 所有一级子节点的list
        if (!listElement.isEmpty()) {
            for (Element e : listElement) {// 遍历所有一级子节点
                if (e.attributes().isEmpty() && e.elements().isEmpty()) // 判断一级节点是否有属性和子节点
                    result.put(e.getName(), e.getTextTrim());// 沒有则将当前节点作为上级节点的属性对待
                else {
                    if (!result.containsKey(e.getName())) // 判断父节点是否存在该一级节点名称的属性
                        result.put(e.getName(), new JSONArray());// 没有则创建
                    ((JSONArray) result.get(e.getName())).add(elementToJSONObject(e));// 将该一级节点放入该节点名称的属性对应的值中
                }
            }
        }
        return result;
    }
}

文件处理工具

	/**
     * 返回文件名
     *
     * @param filePath 文件
     * @return 文件名
     */
    public static String getName(String filePath)
    {
        if (null == filePath)
        {
            return null;
        }
        int len = filePath.length();
        if (0 == len)
        {
            return filePath;
        }
        if (isFileSeparator(filePath.charAt(len - 1)))
        {
            // 以分隔符结尾的去掉结尾分隔符
            len--;
        }

        int begin = 0;
        char c;
        for (int i = len - 1; i > -1; i--)
        {
            c = filePath.charAt(i);
            if (isFileSeparator(c))
            {
                // 查找最后一个路径分隔符(/或者\)
                begin = i + 1;
                break;
            }
        }

        return filePath.substring(begin, len);
    }
    
    /**
     * 下载文件名重新编码
     *
     * @param response 响应对象
     * @param realFileName 真实文件名
     * @return
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
    {
        String percentEncodedFileName = percentEncode(realFileName);

        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=")
                .append(percentEncodedFileName)
                .append(";")
                .append("filename*=")
                .append("utf-8''")
                .append(percentEncodedFileName);

        response.setHeader("Content-disposition", contentDispositionValue.toString());
    }
    
    /**
     * 编码文件名
     */
    public static final String extractFilename(MultipartFile file)
    {
        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
        return fileName;
    }
    
    /**
     * 微信 API get请求
     * @param url 请求路径
     * @return Object
     * @throws IOException io
     */
    public static JSONObject doGet(String url) throws IOException {
        JSONObject jsonObject = null;
        HttpClient client = HttpClientBuilder.create().build();
        final HttpGet httpGet = new HttpGet(url);
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            // 返回结果转化为JSON对象
            final String result = EntityUtils.toString(entity, "UTF-8");
            jsonObject = StringAnalysisXml.documentToJSONObject(result);
        }
        return jsonObject;
    }
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐