美文网首页个人学习
JAVA进阶篇(9)—实现网络照片的上传和下载(腾讯云cos)

JAVA进阶篇(9)—实现网络照片的上传和下载(腾讯云cos)

作者: 小胖学编程 | 来源:发表于2020-09-14 18:19 被阅读0次

    对象存储服务(Cloud Object Service)是面向企业和个人开发者提供的高可用,高稳定,强安全的云端存储服务。您可以将任意数量和形式的非结构化数据放入COS,并在其中实现数据的管理和处理。COS支持标准的Restful API接口,您可以快速上手使用,按实际使用量计费,无最低使用限制。

    1. 代码接入

    1.1 引入依赖

    引入腾讯云cos的依赖jar包。

    <dependency>
        <groupId>com.qcloud</groupId>
        <artifactId>cos_api</artifactId>
        <version>5.6.8</version>
    </dependency>
    <dependency>
         <groupId>com.tencent.cloud</groupId>
         <artifactId>cos-sts-java</artifactId>
         <version>3.0.5</version>
    </dependency>
    

    1.2 网络图片的下载

    网络图片的下载,是将照片读取为base64的格式。注意,读取下来需要加上data:image/png;base64,的前缀(此前缀为png格式)。

    在实际的照片下载中,可以根据文件的后缀类型,转换成对应类型的base64格式的照片信息。

    @Slf4j
    public class ImgUtil {
    
        /**
         * 根据照片的后缀类型转换照片
         *
         * @param netImagePath 网络图片地址,格式必须以xxx.xxx(xxx.png)
         * @return 照片的base64
         */
        public static String NetImageToBase64ByImgSuffix(String netImagePath) {
            String[] split = netImagePath.split("\\.");
            String s = split[split.length - 1];
            //格式
            String prefix = String.format("data:image/%s;base64,", s);
            return NetImageToBase64(netImagePath, prefix);
        }
    
    
        /**
         * 将网络照片转换为base64格式的照片
         *
         * @param netImagePath 原照片地址
         * @param prefix       base64的照片的类型,格式data:image/png;base64,
         * @return base64格式的照片,
         */
        public static String NetImageToBase64(String netImagePath, String prefix) {
            ByteArrayOutputStream data = new ByteArrayOutputStream();
            String strNetImageToBase64;
            try {
                // 创建URL
                URL url = new URL(netImagePath);
                final byte[] by = new byte[1024];
                // 创建链接
                final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                InputStream is = conn.getInputStream();
                // 将内容读取内存中
                int len;
                while ((len = is.read(by)) != -1) {
                    data.write(by, 0, len);
                }
                // 对字节数组Base64编码
                BASE64Encoder encoder = new BASE64Encoder();
                strNetImageToBase64 = prefix + encoder.encode(data.toByteArray());
            } catch (IOException e) {
                log.error("下载失败", e);
                throw new RuntimeException(e);
            }
            return strNetImageToBase64;
        }
    }
    

    1.3 文件的上传

    1. 根据base64的前缀决定上传照片的类型;
    2. 使用腾讯云cos的提供的类实现文件的上传;
    3. url文件目录路径就是存储在cos的文件目录路径;
    @Slf4j
    public class ImgUtil {
    
        /**
         * 保存照片
         * data:image/jpg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD
         *
         * @param base64Str  base64的照片流
         * @param secretId   腾讯云的SecretId(永久的,可在控制台开启或关闭)
         * @param secretKey  腾讯云的SecretKey(永久的,可在控制台开启或关闭)
         * @param region     腾讯云的region(bucket所在地区)
         * @param bucketName 存储桶的名称
         * @return 图片地址
         */
        public static String saveFile(String base64Str, String secretId, String secretKey, String region, String bucketName) {
            String[] d = base64Str.split("base64,");
            String dataPrefix;
            String data;
            if (d.length == 2) {
                dataPrefix = d[0];  //data:image/jpg;格式
                data = d[1]; ///9j/4AAQSkZJRgABAQAAAQABAAD...格式
            } else {
                log.error("上传失败,数据不合法,base64Str:" + base64Str);
                throw new RuntimeException("上传失败,数据不合法");
            }
            String fileName = getFileName(dataPrefix);
            byte[] fileOut = base64ToBytes(data);
            CosClientFactory instance = CosClientFactory.getInstance(secretId, secretKey, region);
            //生成文件名(pro/xxx/www/2020/9/12/UUID.png)
            String fileKey = "pro" + "/xxx" + "/www/" + calculatePath() + fileName;
            //上传到腾讯云
            instance.uploadFile(bucketName, fileKey, fileOut);
            return fileKey;
        }
    
        /**
         * 转换为base64的字节数组
         *
         * @param base64Str base64的字符串
         * @return 字节数组
         */
        public static byte[] base64ToBytes(String base64Str) {
            Assert.notNull(base64Str, "base64Str empty");
            return Base64.decodeBase64(base64Str);
        }
    
        /**
         * 文件的路径,时间单位
         *
         * @return 目录名
         */
        public static String calculatePath() {
            Calendar calendar = Calendar.getInstance();
            String year = String.valueOf(calendar.get(Calendar.YEAR));
            String month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
            String date = String.valueOf(calendar.get(Calendar.DATE));
            //目录名
            return year + "/" + month + "/" + date + "/";
        }
    
        /**
         * 获取文件名:UUID+.后缀
         *
         * @param dataPrix base64的前缀
         * @return 后缀
         */
        public static String getFileName(String dataPrix) {
            String suffix;
            if ("data:image/jpg;".equalsIgnoreCase(dataPrix)) {
                suffix = ".jpg";
            } else if ("data:image/jpeg;".equalsIgnoreCase(dataPrix)) {
                suffix = ".jpg";
            } else if ("data:image/x-icon;".equalsIgnoreCase(dataPrix)) {
                suffix = ".ico";
            } else if ("data:image/gif;".equalsIgnoreCase(dataPrix)) {
                suffix = ".gif";
            } else if ("data:image/png;".equalsIgnoreCase(dataPrix)) {
                suffix = ".png";
            } else {
                throw new RuntimeException("上传图片格式不合法");
            }
            return UUID.randomUUID() + suffix;
        }
    }
    

    文件上传类的相关代码:

    @Slf4j
    public class CosClientFactory {
        private static volatile CosClientFactory cosClientFactory;
    
        //腾讯云的SecretId(永久的,可在控制台开启或关闭)
        private String secretId;
    
        //腾讯云的SecretKey(永久的,可在控制台开启或关闭)
        private String secretKey;
    
        //腾讯云的region(bucket所在地区)
        private String region;
    
        //cos的客户端
        private COSClient cos;
    
        private CosClientFactory(String secretId, String secretKey, String region) {
            this.secretId = secretId;
            this.secretKey = secretKey;
            this.region = region;
        }
    
        /**
         * 单例模式,创建唯一对象。
         * 双锁机制。
         *
         * @param secretId  腾讯云的SecretId
         * @param secretKey 腾讯云的SecretKey
         * @param region    腾讯云的region
         * @return cos的客户端
         */
        public static CosClientFactory getInstance(String secretId, String secretKey, String region) {
            if (cosClientFactory == null) {
                synchronized (CosClientFactory.class) {
                    if (cosClientFactory == null) {
                        cosClientFactory = new CosClientFactory(secretId, secretKey, region);
                    }
                }
                //初始化用户信息
            }
            return cosClientFactory;
        }
    
        /**
         * 上传照片
         */
        public void uploadFile(String bucketName, String fileName, byte[] fileBytes) {
            COSClient cosClient = getCosClient();
            uploadFile2Tx(cosClient, bucketName, fileName, fileBytes);
        }
    
        /**
         * 向腾讯云上传文件
         *
         * @param fileBytes  文件的字节数组
         * @param cosClient  cos客户端
         * @param bucketName 存储桶的名字
         * @param fileName   文件的名字
         * @throws IOException
         */
        public void uploadFile2Tx(COSClient cosClient, String bucketName, String fileName, byte[] fileBytes) {
            ByteArrayInputStream input = null;
            try {
                input = new ByteArrayInputStream(fileBytes);
                ObjectMetadata objectMetadata = new ObjectMetadata();
                // 设置输入流长度
                objectMetadata.setContentLength(input.available());
                // 上传文件。<yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。
                PutObjectResult putObjectResult = cosClient.putObject(bucketName, fileName, input, objectMetadata);
            } catch (CosServiceException serviceExp) {
                log.error("上传文件失败", serviceExp);
                throw serviceExp;
            } catch (CosClientException e) {
                log.error("上传文件失败", e);
            } finally {
                //关闭网络连接
                if (cosClient != null) {
                    cosClient.shutdown();
                }
            }
        }
    
        //调用完毕,需要关闭网络连接
        private COSClient getCosClient() {
            if (null == cos) {
                // 1 初始化用户身份信息(secretId, secretKey)。
                COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
                // 2 设置 bucket 区域。
                ClientConfig clientConfig = new ClientConfig(new Region(region));
                // 3 生成 cos 客户端。
                cos = new COSClient(cred, clientConfig);
            }
            return cos;
        }
    }
    

    1.4 相关的配置

    可以配置在配置文件中进行访问。

    # 这些配置在腾讯云控制台都可查到(使用时替换为你自己的)
    # 腾讯云的SecretId(永久的,可在控制台开启或关闭)
    tencent.SecretId=Dug3RhGtKp8Df4FgAKt7H1ivGH7kfDiJ6UEo
    # 腾讯云的SecretKey(永久的,可在控制台开启或关闭)
    tencent.SecretKey=cGUanub0FYl9pQmpkU3YpyRpB93NdBXf
    # 腾讯云的bucket (存储桶)
    tencent.bucket=dintalk-1228321366
    # 腾讯云的region(bucket所在地区)
    tencent.region=ap-beijing
    # 腾讯云的访问基础链接:
    tencent.baseUrl= https:/dintalk-1228321366.cos.ap-beijing.myqcloud.com/
    

    推荐阅读

    腾讯云COS对象存储的简单使用

    相关文章

      网友评论

        本文标题:JAVA进阶篇(9)—实现网络照片的上传和下载(腾讯云cos)

        本文链接:https://www.haomeiwen.com/subject/cpwaektx.html