腾讯云官方API网址

https://cloud.tencent.com/document/api/436/7751

1、pom依赖

<!--hutool工具类-->
<dependency>
    <groupId>cn.hutool</groupId>
     <artifactId>hutool-all</artifactId>
    <version>5.8.0.M2</version>
</dependency>

<!--    腾讯云    -->
<dependency>
    <groupId>com.qcloud</groupId>
    <artifactId>cos_api</artifactId>
    <version>5.6.155</version>
</dependency>

2、工具类TencentCOSUtil 

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class TencentCOSUtil {

    // COS的SecretId
    private static String SECRET_ID = "自己的SecretId";

    // COS的SecretKey
    private static String SECRET_KEY = "自己的SecretKey";

    //https://存储桶名称-1303******.cos.地域全拼.myqcloud.com/
    private static String ROOT_SRC = "https://存储桶名称-1303******.cos.地域全拼.myqcloud.com/";

    // 上传的存储桶的地域,可参考在COS的后台能查询,示例:ap-beijing
    private static String BUCKET_ADDR = "地域全拼";

    // 存储桶的名字
    private static String BUCKET_NAME = "自己的存储桶名称";

    /**
     * 1.调用静态方法getCosClient()就会获得COSClient实例
     * 2.本方法根据永久密钥初始化 COSClient的,官方是不推荐,官方推荐使用临时密钥,是可以限制密钥使用权限,创建cred时有些区别
     *
     * @return COSClient实例
     */
    private static COSClient getCosClient() {
        // 1 初始化用户身份信息(secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(SECRET_ID, SECRET_KEY);
        // 2.1 设置存储桶的地域(上文获得)
        Region region = new Region(BUCKET_ADDR);
        ClientConfig clientConfig = new ClientConfig(region);
        // 2.2 使用https协议传输
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 3 生成 cos 客户端
        COSClient cosClient = new COSClient(cred, clientConfig);
        // 返回COS客户端
        return cosClient;
    }

    /**
     * 上传文件
     *
     * @param file
     * @return 返回文件的url
     */
    public static String upLoadFile(MultipartFile file) {
        try {
            // 获取上传的文件的输入流
            InputStream inputStream = file.getInputStream();

            // 避免文件覆盖,获取文件的原始名称,如123.jpg,然后通过截取获得文件的后缀,也就是文件的类型
            String originalFilename = file.getOriginalFilename();
            // 获取文件的类型
            String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 使用UUID工具  创建唯一名称,放置文件重名被覆盖,在拼接上上命令获取的文件类型
            String fileName = UUID.randomUUID().toString() + fileType;
            // 指定文件上传到 COS 上的路径,即对象键最终文件会传到存储桶名字中的images文件夹下的fileName名字
            String key = "自定义路径/" + fileName;
            // 创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // - 使用输入流存储,需要设置请求长度
            objectMetadata.setContentLength(inputStream.available());
            // - 设置缓存
            objectMetadata.setCacheControl("no-cache");
            // - 设置Content-Type
            objectMetadata.setContentType(fileType);
            // 上传文件
            PutObjectResult putResult = getCosClient().putObject(BUCKET_NAME, key, inputStream, objectMetadata);
            // 创建文件的网络访问路径
            String url = ROOT_SRC + DateUtil.today() + "/" + key;
            // 关闭 cosClient,并释放 HTTP 连接的后台管理线程
            getCosClient().shutdown();
            return url;

        } catch (Exception e) {
            e.printStackTrace();
            // 发生IO异常、COS连接异常等,返回空
            return null;
        }
    }

    /**
     * 上传Base64图片
     *
     * @param base64Data base64编码的图片数据(可以包含data:image/png;base64,前缀)
     * @return 返回文件的url,上传失败返回null
     */
    public static String upLoadBase64Image(String base64Data) {
        return upLoadBase64Image(base64Data, null);
    }

    /**
     * 上传Base64图片
     *
     * @param base64Data base64编码的图片数据(可以包含data:image/png;base64,前缀)
     * @param fileName   自定义文件名(不包含扩展名),如果为null则使用UUID生成
     * @return 返回文件的url,上传失败返回null
     */
    public static String upLoadBase64Image(String base64Data, String fileName) {
        COSClient cosClient = null;
        try {
            // 验证base64数据
            if (StrUtil.isBlank(base64Data)) {
                return null;
            }

            // 清理base64数据(移除可能的data:image/png;base64,前缀)
            String cleanedBase64 = cleanBase64Data(base64Data);
            if (StrUtil.isBlank(cleanedBase64)) {
                return null;
            }

            // 解码base64数据
            byte[] imageBytes = Base64.getDecoder().decode(cleanedBase64);

            // 根据base64前缀或文件扩展名确定文件类型
            String fileType = getFileTypeFromBase64(base64Data);
            if (fileType == null) {
                // 如果没有找到明确的文件类型,尝试从数据内容判断(简单判断)
                fileType = detectImageType(imageBytes);
                if (fileType == null) {
                    fileType = ".jpg"; // 默认使用jpg
                }
            }

            // 生成文件名
            if (StrUtil.isBlank(fileName)) {
                fileName = UUID.randomUUID().toString();
            }
            String fullFileName = fileName + fileType;

            // 指定文件上传到 COS 上的路径
            // images/2026-01-01/xxx
            String key = "自定义路径名称/"+DateUtil.today()+"/" + fullFileName;

            // 创建输入流
            InputStream inputStream = new ByteArrayInputStream(imageBytes);

            // 创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(imageBytes.length);
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setContentType(getContentType(fileType));

            // 获取COS客户端
            cosClient = getCosClient();

            // 上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, key, inputStream, objectMetadata);
            cosClient.putObject(putObjectRequest);

            // 创建文件的网络访问路径
            String url = ROOT_SRC + key;
            return url;

        } catch (Exception e) {
            e.printStackTrace();
            // 发生异常,返回空
            return null;
        } finally {
            // 关闭cosClient
            if (cosClient != null) {
                cosClient.shutdown();
            }
        }
    }

    /**
     * 清理base64数据,移除data:image/png;base64,前缀
     *
     * @param base64Data 原始base64数据
     * @return 清理后的base64数据
     */
    private static String cleanBase64Data(String base64Data) {
        if (base64Data.contains("base64,")) {
            return base64Data.substring(base64Data.indexOf("base64,") + 7);
        }
        return base64Data;
    }

    /**
     * 从base64数据中获取文件类型
     *
     * @param base64Data base64数据
     * @return 文件扩展名,如 ".jpg", ".png" 等
     */
    private static String getFileTypeFromBase64(String base64Data) {
        // 匹配data:image/类型;base64,格式
        Pattern pattern = Pattern.compile("data:image/(.*?);base64,");
        Matcher matcher = pattern.matcher(base64Data);
        if (matcher.find()) {
            String imageType = matcher.group(1).toLowerCase();
            switch (imageType) {
                case "jpeg":
                case "jpg":
                    return ".jpg";
                case "png":
                    return ".png";
                case "gif":
                    return ".gif";
                case "bmp":
                    return ".bmp";
                case "webp":
                    return ".webp";
                case "svg+xml":
                    return ".svg";
                default:
                    return "." + imageType;
            }
        }
        return null;
    }

    /**
     * 根据字节数据检测图片类型
     *
     * @param bytes 图片字节数据
     * @return 文件扩展名
     */
    private static String detectImageType(byte[] bytes) {
        if (bytes.length < 4) {
            return null;
        }

        // 检查PNG
        if (bytes[0] == (byte) 0x89 && bytes[1] == (byte) 0x50 &&
                bytes[2] == (byte) 0x4E && bytes[3] == (byte) 0x47) {
            return ".png";
        }

        // 检查JPEG
        if (bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xD8) {
            return ".jpg";
        }

        // 检查GIF
        if (bytes[0] == (byte) 0x47 && bytes[1] == (byte) 0x49 &&
                bytes[2] == (byte) 0x46 && bytes[3] == (byte) 0x38) {
            return ".gif";
        }

        // 检查BMP
        if (bytes[0] == (byte) 0x42 && bytes[1] == (byte) 0x4D) {
            return ".bmp";
        }

        // 检查WEBP
        if (bytes[0] == (byte) 0x52 && bytes[1] == (byte) 0x49 &&
                bytes[2] == (byte) 0x46 && bytes[3] == (byte) 0x46) {
            if (bytes.length >= 12 && bytes[8] == (byte) 0x57 &&
                    bytes[9] == (byte) 0x45 && bytes[10] == (byte) 0x42 &&
                    bytes[11] == (byte) 0x50) {
                return ".webp";
            }
        }

        return null;
    }

    /**
     * 根据文件扩展名获取Content-Type
     *
     * @param fileType 文件扩展名
     * @return Content-Type字符串
     */
    private static String getContentType(String fileType) {
        switch (fileType.toLowerCase()) {
            case ".jpg":
            case ".jpeg":
                return "image/jpeg";
            case ".png":
                return "image/png";
            case ".gif":
                return "image/gif";
            case ".bmp":
                return "image/bmp";
            case ".webp":
                return "image/webp";
            case ".svg":
                return "image/svg+xml";
            default:
                return "application/octet-stream";
        }
    }
}

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐