• COSClient上传图片失败


    目录

    1、准备配置

     2、解决问题


    1、准备配置

    任何一个东西,都是从0到1的过程,解决问题之前,我们得先有一个账号(已有账号可以跳过此步骤)

    • 首先,我们准备一个腾讯云(https://cloud.tencent.com/)的账号(没有就注册一个),然后首页选择对象存储,点击立即使用跳转;

    •  然后登录进来后看到这个,可以免费使用6个月,还是感觉不错的,虽然买一般的也不贵,但是有便宜不占是孙子,哈哈

    • 现在我们就可以来创建一个存储桶了,这里注意访问权限选择公有读写,不然图片上传成功后无法预览

    • 创建成功后,点击列表的存储桶名称或配置管理,就可以查看桶的一些配置,比如可以新建个文件存放图片啥的。然后我们再选择密钥管理,新建一个密钥(APPID),SecretId、SecretKey用于代码里面的配置。

    废话不多说,上代码

    public class QCloudUtil {
        
        public static ResponseVo writeFile(CloudStorageConfigVo cloudStorageConfig, String filePath, MultipartFile file) {
            String accessKey = cloudStorageConfig.getQcloudSecretId();
            String secretKey = cloudStorageConfig.getQcloudSecretKey();
            String bucket =  cloudStorageConfig.getQcloudRegion();
            // bucket的命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式
            String bucketName = cloudStorageConfig.getQcloudBucketName();
            // 1 初始化用户身份信息(secretId, secretKey)
            COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey);
            // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
            ClientConfig clientConfig = new ClientConfig(new Region(bucket));
            // 3 生成cos客户端
            COSClient cosclient = new COSClient(cred, clientConfig);
            // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口
            // 大文件上传请参照 API 文档高级 API 上传
            File localFile = null;
            try {
                localFile = File.createTempFile("temp",null);
                file.transferTo(localFile);
                // 指定要上传到 COS 上的路径
                String key = filePath;
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
                PutObjectResult putObjectResult = cosclient.putObject(putObjectRequest);
                return new ResponseVo(CoreConst.SUCCESS_CODE,"上传成功");
            } catch (IOException e) {
                return new ResponseVo(CoreConst.FAIL_CODE,e.getMessage());
            }finally {
                // 关闭客户端(关闭后台线程)
                cosclient.shutdown();
            }
        }
    
    }

     

    • 云配置类
    /**
     * 云存储配置信息
     */
    public class CloudStorageConfigVo {
        //类型 1:七牛  2:阿里云  3:腾讯云
        private Integer type;
    
        //七牛绑定的域名
        private String qiniuDomain="";
        //七牛路径前缀
        private String qiniuPrefix="";
        //七牛ACCESS_KEY
        private String qiniuAccessKey="";
        //七牛SECRET_KEY
        private String qiniuSecretKey="";
        //七牛存储空间名
        private String qiniuBucketName="";
    
        //阿里云绑定的域名
        private String aliyunDomain="";
        //阿里云路径前缀
        private String aliyunPrefix="";
        //阿里云EndPoint
        private String aliyunEndPoint="";
        //阿里云AccessKeyId
        private String aliyunAccessKeyId="";
        //阿里云AccessKeySecret
        private String aliyunAccessKeySecret="";
        //阿里云BucketName
        private String aliyunBucketName="";
    
        //腾讯云绑定的域名
        private String qcloudDomain="";
        //腾讯云路径前缀
        private String qcloudPrefix="";
        //腾讯云AppId
        private Integer qcloudAppId;
        //腾讯云SecretId
        private String qcloudSecretId="";
        //腾讯云SecretKey
        private String qcloudSecretKey="";
        //腾讯云BucketName
        private String qcloudBucketName="";
        //腾讯云COS所属地区
        private String qcloudRegion="";
    
        
    }

     

    • 上传图片代码*(Java已经实现了MD5、SHA1算法。利用java.security.MessageDigest类就可以获取字符串和文件的MD5以及SHA1结果)
    //腾讯云对象存储
        @ResponseBody
        @PostMapping(value = "/upload")
        public UploadResponse upload(@RequestParam(value = "file", required = false) MultipartFile file) throws Exception {
            if(file == null || file.isEmpty()) {
                throw new UploadFileNotFoundException(UploadResponse.Error.FILENOTFOUND);
            }
            try {
                String originalFileName = file.getOriginalFilename();
                String suffix = originalFileName.substring(originalFileName.lastIndexOf(".")).toLowerCase();
                // 数据库查询云配置
                String value = sysConfigService.selectAll().get(SysConfigKey.CLOUD_STORAGE_CONFIG.getValue());
                Gson gson = new Gson();
                // 转换为一个配置对象
                CloudStorageConfigVo cloudStorageConfig = gson.fromJson(value, CloudStorageConfigVo.class);
                //获取腾讯云路径前缀
                String dir = cloudStorageConfig.getQcloudPrefix();
                // 获取字符串的MD5结果,file.getBytes()--输入的字符串转换成字节数组
                String md5 = MD5.getMessageDigest(file.getBytes());
                String filePath = String.format("%1$s/%2$s%3$s", dir, md5, suffix);
                ResponseVo responseVo = QCloudUtil.writeFile(cloudStorageConfig, filePath, file);
                String qCloudDomain = cloudStorageConfig.getQcloudDomain();
                String url = String.format("%1$s/%2$s", qCloudDomain, filePath);
                if(responseVo.getStatus().equals(CoreConst.SUCCESS_CODE)){
                    return  new UploadResponse(url,originalFileName, suffix, url, CoreConst.SUCCESS_CODE);
                }else{
                    return  new UploadResponse(originalFileName,  CoreConst.FAIL_CODE,responseVo.getMsg());
                }
            } catch (Exception e) {
                logger.error(String.format("UploadController.upload%s", e));
                throw e;
            }
        }

     

    • MD5

    • (Java中的 << 、<<、 >>>表示:)

    • <<  表示左移,不分正负数,低位补0
    • >>  表示右移,如果该数为正,则高位补0,若为负数,则高位补1
    • >>> 表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0
    public class MD5 {
    
        private MD5() {
        }
    
        public final static String getMessageDigest(byte[] buffer) {
            //首先初始化一个字符数组,用来存放每个16进制字符
            char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
            try {
                // 拿到一个MD5转换器(如果想要SHA1参数换成"SHA1")
                MessageDigest mdTemp = MessageDigest.getInstance ("MD5");
                // buffer 是输入字符串转换得到的字节数组
                mdTemp.update (buffer);
                // 转换并返回结果,也是字节数组,包含16个元素
                byte[] md = mdTemp.digest ();
    
                int j = md.length;
                // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
                char str[] = new char[j * 2];
                int k = 0;
                //遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
                for (int i = 0; i < j; i++) {
                    byte byte0 = md[i];
                    str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    str[k++] = hexDigits[byte0 & 0xf];
                }
                //字符数组转换成字符串返回
                return new String (str);
            } catch (Exception e) {
                return null;
            }
        }
    
        public static String hex(byte[] array) {
            StringBuffer sb = new StringBuffer ();
            for (int i = 0; i < array.length; ++i) {
                sb.append (Integer.toHexString ((array[i]
                        & 0xFF) | 0x100).substring (1, 3));
            }
            return sb.toString ();
        }
    
        public static String md5Hex(String message) {
            try {
                MessageDigest md =
                        MessageDigest.getInstance ("MD5");
                return hex (md.digest (message.getBytes ("CP1252")));
            } catch (NoSuchAlgorithmException e) {
            } catch (UnsupportedEncodingException e) {
            }
            return null;
        }
    }

     

     

     2、解决问题

    • 重现问题,上传图片的时候提示上传失败,显示异常信息
    com.qcloud.cos.exception.CosClientException:
    please make sure bucket name must contain legal appid when appid is missing. example: music-1251122334

     

    这个是什么意思,就是说我们的桶名称不符合,为什么呢,我们查看一下 COSClient类 的源码,我们直接通过快捷键搜索一下 报错信息中的 music-1251122334,找到这么一个方法,

    // 格式化bucket, 是bucket返回带appid 
    private String formatBucket(String bucketName, String appid) throws CosClientException {
            String parrtern;
            if (appid == null) {
                // 正则表达式匹配
                parrtern = ".*-(125|100)[0-9]{3,}$";
                if (Pattern.matches(parrtern, bucketName)) {
                    return bucketName;
                } else {
                    throw new CosClientException("please make sure bucket name must contain legal appid when appid is missing. example: music-1251122334");
                }
            } else {
                parrtern = "-" + appid;
                return bucketName.endsWith(parrtern) ? bucketName : bucketName + parrtern;
            }
        }

     

    Pattern与Matcher一起合作.Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持. 单独用Pattern只能使用Pattern.matches(String regex,CharSequence input)一种最基础最简单的匹配。

    • 报异常的原因那就是我们的bucketName没有跟提供的规则匹配上,那规则是什么呢,就是这句,只匹配了125、100开头,但是我们的是130开头的,比如我的:wxb-1301890880
    String parrtern = ".*-(125|100)[0-9]{3,}$";

     

    解决的办法就是更新依赖包,之前使用的是5.2.4版本,现在替换为5.6.8版本。

    <!--腾讯云存储依赖-->
            <dependency>
                <groupId>com.qcloud</groupId>
                <artifactId>cos_api</artifactId>
                <version>5.6.8</version>
            </dependency>

     



     

  • 相关阅读:
    ld: cannot find lgcc_s
    Ubuntu 12.10 图形显示未知
    awk分析Nginx日志中的cookie
    Ubuntu 10.04 WPS 问题汇总
    objc[20556]:Class JavaLaunchHelper is implemented in both xxx 警告处理
    在Linux安装配置Tomcat 并部署web应用 ( 三种方式 )
    Spring Boot 系列(二)单元测试&网络请求
    Java自定义注解
    Spring Boot 系列(一)快速入门
    Spring 自定义注解,配置简单日志注解
  • 原文地址:https://www.cnblogs.com/wxb2010/p/12731252.html
Copyright © 2020-2023  润新知