Java springboot项目引入腾讯云COS实现上传
pom.xml
<!--腾讯云上传图片pom依赖--> <dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>5.6.24</version> </dependency>
配置类CosConfig.java
package com.dongao.support.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 腾讯云上传参数 * @author: dongao * @create: 2019/10/16 */ @Component @ConfigurationProperties(prefix = "cos") public class CosConfig { private String secretId = "腾讯云控制台项目配置secretId"; private String secretKey = "腾讯云控制台项目配置secretKey"; private String region = "存储桶地域"; private String bucketName = "存储桶名称"; private String projectName = "业务项目名称"; private String common = "common"; private String imageSize = "2"; private String prefixDomain = "CDN加速域名"; private Long expiration = 60L; public String getSecretId() { return secretId; } public void setSecretId(String secretId) { this.secretId = secretId; } public String getSecretKey() { return secretKey; } public void setSecretKey(String secretKey) { this.secretKey = secretKey; } public String getRegion() { return region; } public void setRegion(String region) { this.region = region; } public String getBucketName() { return bucketName; } public void setBucketName(String bucketName) { this.bucketName = bucketName; } public String getProjectName() { return projectName; } public void setProjectName(String projectName) { this.projectName = projectName; } public String getCommon() { return common; } public void setCommon(String common) { this.common = common; } public String getImageSize() { return imageSize; } public void setImageSize(String imageSize) { this.imageSize = imageSize; } public String getPrefixDomain() { return prefixDomain; } public void setPrefixDomain(String prefixDomain) { this.prefixDomain = prefixDomain; } public Long getExpiration() { return expiration; } public void setExpiration(Long expiration) { this.expiration = expiration; } }
此处给的为默认值,如需改变对应参数,需在application.properties中进行配置
## 腾讯云相关配置 cos.bucketName=testbucket-APPID cos.projectName=local_qsbase cos.businessName=knowledge_point cos.prefixDomain=http://ei-d-files.dongao.com/ cos.imageSize=20 cos.expiration=1
上传工具类CosClientUtil.java
package com.dongao.support.utils; import com.dongao.support.config.CosConfig; 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.exception.CosClientException; import com.qcloud.cos.http.HttpMethodName; import com.qcloud.cos.model.*; import com.qcloud.cos.region.Region; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.spring.SpringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; /** * 上传工具类 * @author: dongao * @create: 2019/10/16 */ public class CosClientUtil { private static CosConfig cosConfig = SpringUtils.getBean(CosConfig.class); /**初始化密钥信息*/ private COSCredentials cred = new BasicCOSCredentials(cosConfig.getSecretId(), cosConfig.getSecretKey()); /**初始化客户端配置,设置bucket所在的区域*/ private ClientConfig clientConfig = new ClientConfig(new Region(cosConfig.getRegion())); /**初始化cOSClient*/ private COSClient cosClient = new COSClient(cred, clientConfig); /** * 上传图片 * @param file * @param businessName * @return * @throws Exception */ public String uploadImgToCos(MultipartFile file, String businessName) throws Exception { int imageSize = Integer.parseInt(cosConfig.getImageSize()); int maxSize = imageSize << 20; if (file.getSize() > maxSize) { throw new Exception("上传文件大小不能超过"+imageSize+"M!"); } if (StringUtils.isEmpty(businessName)) { businessName = cosConfig.getCommon(); } //生成文件夹层级 Calendar cale = Calendar.getInstance(); int year = cale.get(Calendar.YEAR); SimpleDateFormat sdf = new SimpleDateFormat("MM"); Date dd = cale.getTime(); String month = sdf.format(dd); String folderName = cosConfig.getProjectName()+"/image/"+businessName+"/"+year+"/"+month+"/"; //图片名称 String originalFilename = file.getOriginalFilename(); Random random = new Random(); //生成新的图片名称(随机数0-9999+系统当前时间+上传图片名) String name; if (originalFilename.lastIndexOf(".") != -1) { name = random.nextInt(10000) + System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf(".")); }else { String extension = FileUploadUtils.getExtension(file); name = random.nextInt(10000) + System.currentTimeMillis() + "." + extension; } //生成对象键 String key = folderName+name; try { InputStream inputStream = file.getInputStream(); this.uploadFileToCos(inputStream, key); //return "http://" + cosConfig.getBucketName() + ".cos."+cosConfig.getRegion()+".myqcloud.com/" + key; return key; } catch (Exception e) { throw new Exception("文件上传失败"); } } /** * 以文件流方式上传图片 * @param is * @param businessName * @param originalFilename * @param fileSize * @return * @throws Exception */ public String uploadImgToCos(InputStream is, String originalFilename, long fileSize, String businessName) throws Exception { int imageSize = Integer.parseInt(cosConfig.getImageSize()); int maxSize = imageSize << 20; if (fileSize > maxSize) { throw new Exception("上传文件大小不能超过"+imageSize+"M!"); } if (StringUtils.isEmpty(businessName)) { businessName = cosConfig.getCommon(); } //生成文件夹层级 Calendar cale = Calendar.getInstance(); int year = cale.get(Calendar.YEAR); SimpleDateFormat sdf = new SimpleDateFormat("MM"); Date dd = cale.getTime(); String month = sdf.format(dd); String folderName = cosConfig.getProjectName()+"/image/"+businessName+"/"+year+"/"+month+"/"; //图片名称 Random random = new Random(); //生成新的图片名称(随机数0-9999+系统当前时间+上传图片名) String name = random.nextInt(10000) + System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf(".")); //生成对象键 String key = folderName+name; try { this.uploadFileToCos(is, key); //return "http://" + cosConfig.getBucketName() + ".cos."+cosConfig.getRegion()+".myqcloud.com/" + key; return key; } catch (Exception e) { throw new Exception("文件上传失败"); } } /** * 上传到COS服务器 如果同名文件会覆盖服务器上的 * @param instream * @param key * @return 出错返回"" ,唯一MD5数字签名 */ public String uploadFileToCos(InputStream instream, String key) { String etag = ""; try { // 创建上传Object的Metadata ObjectMetadata objectMetadata = new ObjectMetadata(); // 设置输入流长度为500 objectMetadata.setContentLength(instream.available()); // 设置 Content type objectMetadata.setContentType(getcontentType(key.substring(key.lastIndexOf(".")))); // 上传文件 PutObjectResult putResult = cosClient.putObject(cosConfig.getBucketName(), key, instream, objectMetadata); etag = putResult.getETag(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (instream != null) { //关闭输入流 instream.close(); } // 关闭客户端(关闭后台线程) cosClient.shutdown(); } catch (IOException e) { e.printStackTrace(); } } return etag; } /** * Description: 判断Cos服务文件上传时文件的contentType * @param filenameExtension 文件后缀 * @return String */ public String getcontentType(String filenameExtension) { String bmp = "bmp"; if (bmp.equalsIgnoreCase(filenameExtension)) { return "image/bmp"; } String gif = "gif"; if (gif.equalsIgnoreCase(filenameExtension)) { return "image/gif"; } String jpeg = "jpeg"; String jpg = "jpg"; String png = "png"; if (jpeg.equalsIgnoreCase(filenameExtension) || jpg.equalsIgnoreCase(filenameExtension) || png.equalsIgnoreCase(filenameExtension)) { return "image/jpeg"; } String html = "html"; if (html.equalsIgnoreCase(filenameExtension)) { return "text/html"; } String txt = "txt"; if (txt.equalsIgnoreCase(filenameExtension)) { return "text/plain"; } String vsd = "vsd"; if (vsd.equalsIgnoreCase(filenameExtension)) { return "application/vnd.visio"; } String pptx = "pptx"; String ppt = "ppt"; if (pptx.equalsIgnoreCase(filenameExtension) || ppt.equalsIgnoreCase(filenameExtension)) { return "application/vnd.ms-powerpoint"; } String docx = ".docx"; String doc = ".doc"; if (docx.equalsIgnoreCase(filenameExtension) || doc.equalsIgnoreCase(filenameExtension)) { return "application/msword"; } String xml = "xml"; if (xml.equalsIgnoreCase(filenameExtension)) { return "text/xml"; } String mp4 = ".mp4"; if (mp4.equalsIgnoreCase(filenameExtension)) { return "application/octet-stream"; } String pdf = ".pdf"; if (pdf.equalsIgnoreCase(filenameExtension)) { // 使用流的形式进行上传,防止下载文件的时候访问url会预览而不是下载。 return "application/pdf"; return "application/octet-stream"; } String xls = ".xls"; String xlsx = ".xlsx"; if (xls.equalsIgnoreCase(filenameExtension) || xlsx.equalsIgnoreCase(filenameExtension)) { return "application/vnd.ms-excel"; } String mp3 = ".mp3"; if (mp3.equalsIgnoreCase(filenameExtension)) { return "audio/mp3"; } String wav = ".wav"; if (wav.equalsIgnoreCase(filenameExtension)) { return "audio/wav"; } return "image/jpeg"; } /** * 获取预签名URL * @param urlKey * @return */ public String getPresignedUrl(String urlKey) { URL url = null; try { GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(cosConfig.getBucketName(), urlKey, HttpMethodName.GET); // 设置签名过期时间(可选), 若未进行设置, 则默认使用 ClientConfig 中的签名过期时间(1小时) // 可以设置任意一个未来的时间,推荐是设置 10 分钟到 3 天的过期时间 // 这里设置签名在半个小时后过期 Date expirationDate = new Date(System.currentTimeMillis() + cosConfig.getExpiration() * 60L * 1000L); req.setExpiration(expirationDate); url = cosClient.generatePresignedUrl(req); } catch (CosClientException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } return url.toString(); } /** * 获取预签名URL * @param urlKey 资源路径 * @param requestParameter 本次请求的参数 * @param customRequestHeader 本次请求的头部。Host 头部会自动补全,不需要填写 * @return */ public String getPresignedUrl(String urlKey, Map<String,String> requestParameter,Map<String,String> customRequestHeader) { URL url = null; try { GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(cosConfig.getBucketName(), urlKey, HttpMethodName.GET); // 设置签名过期时间(可选), 若未进行设置, 则默认使用 ClientConfig 中的签名过期时间(1小时) // 可以设置任意一个未来的时间,推荐是设置 10 分钟到 3 天的过期时间 // 这里设置签名在半个小时后过期 Date expirationDate = new Date(System.currentTimeMillis() + cosConfig.getExpiration() * 60L * 1000L); req.setExpiration(expirationDate); // 填写本次请求的参数 if (!requestParameter.isEmpty()) { Iterator<Map.Entry<String, String>> iterator = requestParameter.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> next = iterator.next(); String key = next.getKey(); String value = next.getValue(); req.addRequestParameter(key, value); } } // 填写本次请求的头部。Host 头部会自动补全,不需要填写 if (!customRequestHeader.isEmpty()) { Iterator<Map.Entry<String, String>> iterator = customRequestHeader.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> next = iterator.next(); String key = next.getKey(); String value = next.getValue(); req.putCustomRequestHeader(key, value); } } url = cosClient.generatePresignedUrl(req); } catch (CosClientException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } return url.toString(); } /** * 在指定账号下创建一个存储桶。同一用户账号下,可以创建多个存储桶,数量上限是200个(不区分地域),存储桶中的对象数量没有限制。 * 创建存储桶是低频操作,一般建议在控制台创建 Bucket,在 SDK 进行 Object 的操作。 * @return */ public Bucket createBucket(String bucketName) { Bucket bucketResult = null; try { //存储桶名称,格式:BucketName-APPID String bucket = bucketName+"-1252590610"; CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucket); // 设置 bucket 的权限为 Private(私有读写), 其他可选有公有读私有写, 公有读写 createBucketRequest.setCannedAcl(CannedAccessControlList.Private); bucketResult = cosClient.createBucket(createBucketRequest); } catch (CosClientException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } return bucketResult; } /** * 查询指定账号下所有的存储桶列表 * @return */ public List<Bucket> listBuckets() { List<Bucket> buckets = null; try { // 如果只调用 listBuckets 方法,则创建 cosClient 时指定 region 为 new Region("") 即可 buckets = cosClient.listBuckets(); } catch (CosClientException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } return buckets; } /** * 检索存储桶是否存在且是否有权限访问 * @param bucketName * @return */ public boolean doesBucketExist(String bucketName) { boolean bucketExistFlag = false; try { // bucket的命名规则为 BucketName-APPID ,此处填写的存储桶名称必须为此格式 String bucket = bucketName+"-1252590610"; bucketExistFlag = cosClient.doesBucketExist(bucket); } catch (CosClientException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } return bucketExistFlag; } /** * 删除指定账号下的空存储桶 * @param bucketName */ public void deleteBucket(String bucketName){ try { // bucket的命名规则为 BucketName-APPID ,此处填写的存储桶名称必须为此格式 String bucket = bucketName+"-1252590610"; cosClient.deleteBucket(bucket); } catch (CosClientException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } } /** * 获取存储桶的权限信息 * @param bucketName * @return */ public CannedAccessControlList getBucketAcl(String bucketName) { CannedAccessControlList cannedAccessControlList = null; try { // bucket的命名规则为 BucketName-APPID ,此处填写的存储桶名称必须为此格式 String bucket = bucketName+"-1252590610"; AccessControlList accessControlList = cosClient.getBucketAcl(bucket); // 将存储桶权限转换为预设 ACL, 可选值为:Private, PublicRead, PublicReadWrite cannedAccessControlList = accessControlList.getCannedAccessControl(); } catch (CosClientException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } return cannedAccessControlList; } }
注:日常工作记录,方便后续查阅,也为大家提供方便