Skip to content

Commit

Permalink
feat: add tencent cos
Browse files Browse the repository at this point in the history
  • Loading branch information
lichong-a committed Aug 6, 2024
1 parent ab41a27 commit a8c0786
Show file tree
Hide file tree
Showing 10 changed files with 296 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright 2024 李冲. All rights reserved.
*
*/

package org.funcode.portal.server.common.core.config;

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.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @author 李冲
* @see <a href="https://lichong.work">李冲博客</a>
* @since 0.0.1
*/
@Data
@ConfigurationProperties(prefix = "application.cos")
@Configuration
public class COSConfig {

/**
* 腾讯云控制台项目配置secretId
*/
private String secretId;

/**
* 腾讯云控制台项目配置secretKey
*/
private String secretKey;
/**
* 存储桶地域
*/
private String region;
/**
* 存储桶名称
*/
private String bucketName = "ielts-online-1312690188";
/**
* 业务项目名称
*/
private String projectName = "ielts-online";
/**
* 公共目录
*/
private String common = "common";
/**
* 图片大小
*/
private String imageSize = "2";
/**
* CDN加速域名
*/
private String prefixDomain = "";

/**
* 创建 COSClient 实例,这个实例用来后续调用请求
*
* @return COSClient
*/
@Bean
public COSClient createCOSClient() {
// 设置用户身份信息。
// SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);

// ClientConfig 中包含了后续请求 COS 的客户端设置:
ClientConfig clientConfig = new ClientConfig();

// 设置 bucket 的地域
// COS_REGION 请参见 https://cloud.tencent.com/document/product/436/6224
clientConfig.setRegion(new Region(region));

// 以下的设置,是可选的:

// 设置 socket 读取超时,默认 30s
// clientConfig.setSocketTimeout(30*1000);
// 设置建立连接超时,默认 30s
// clientConfig.setConnectionTimeout(30*1000);

// 如果需要的话,设置 http 代理,ip 以及 port
// clientConfig.setHttpProxyIp("httpProxyIp");
// clientConfig.setHttpProxyPort(80);

// 生成 cos 客户端。
return new COSClient(cred, clientConfig);
}

/**
* 创建 TransferManager 实例,这个实例用来后续调用高级接口
*/
@Bean
public TransferManager createTransferManager() {
// 创建一个 COSClient 实例,这是访问 COS 服务的基础实例。
// 详细代码参见本页: 简单操作 -> 创建 COSClient
COSClient cosClient = createCOSClient();

// 自定义线程池大小,建议在客户端与 COS 网络充足(例如使用腾讯云的 CVM,同地域上传 COS)的情况下,设置成16或32即可,可较充分的利用网络资源
// 对于使用公网传输且网络带宽质量不高的情况,建议减小该值,避免因网速过慢,造成请求超时。
ExecutorService threadPool = Executors.newFixedThreadPool(32);

// 传入一个 threadpool, 若不传入线程池,默认 TransferManager 中会生成一个单线程的线程池。
return new TransferManager(cosClient, threadPool);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright 2024 李冲. All rights reserved.
*
*/

package org.funcode.portal.server.common.core.util;

import jakarta.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;

/**
* @author 李冲
* @see <a href="https://lichong.work">李冲博客</a>
* @since 0.0.1
*/
@Slf4j
public class FileUtils {

/**
* MultipartFile 转 File
*
* @param file MultipartFile 对象
* @throws Exception 转换异常
*/
public static File multipartFileToFile(@Nonnull MultipartFile file) throws Exception {
File toFile = null;
if (file.getSize() > 0) {
InputStream ins;
ins = file.getInputStream();
toFile = new File(Objects.requireNonNull(file.getOriginalFilename()));
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
}

//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
log.error("inputStreamToFile error", e);
}
}

/**
* 删除本地临时文件
*
* @param file
*/
public static void delteTempFile(File file) {
if (file != null) {
File del = new File(file.toURI());
del.delete();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,16 @@ public class Storage extends BaseEntity {
private int fileType;

@Column(length = 200, nullable = false)
@Comment("地址")
private String address;
@Comment("桶名称")
private String bucketName;

@Column(length = 300, nullable = false)
@Comment("唯一标识")
private String key;

@Column(length = 200, nullable = false)
@Comment("版本ID")
private String versionId;

@OneToOne(mappedBy = "storage", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JsonIgnore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
package org.funcode.portal.server.module.ielts.storage.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.funcode.portal.server.common.core.base.http.response.ResponseResult;
import org.funcode.portal.server.module.ielts.storage.domain.vo.StorageAddOrEditVo;
import org.funcode.portal.server.module.ielts.storage.service.IStorageService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.bind.annotation.*;

/**
* @author 李冲
Expand All @@ -30,7 +29,14 @@ public class StorageController {

@Operation(summary = "上传文件")
@PostMapping("/upload")
public ResponseResult<Boolean> upload(MultipartFile file) {
return ResponseResult.success(storageService.upload(file));
public ResponseResult<Boolean> upload(@RequestBody StorageAddOrEditVo storageAddOrEditVo) {
return ResponseResult.success(storageService.upload(storageAddOrEditVo));
}

@Operation(summary = "删除文件")
@GetMapping("/delete")
public ResponseResult<Boolean> delete(@RequestParam @Parameter(description = "存储ID") Long storageId) {
return ResponseResult.success(storageService.deleteStorage(storageId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

/**
* @author 李冲
Expand All @@ -35,9 +36,8 @@ public class StorageAddOrEditVo {
@Schema(description = "文件类型(0:图片;1:音频;2:视频;3:markdown)")
private int fileType;

@Size(max = 200, message = "{ielts.domain.vo.StorageAddOrEditVo.address.Size}")
@NotNull(message = "{ielts.domain.vo.StorageAddOrEditVo.address.NotNull}")
@Schema(description = "地址")
private String address;
@NotNull(message = "{ielts.domain.vo.StorageAddOrEditVo.file.NotNull}")
@Schema(description = "文件")
private MultipartFile file;

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import org.funcode.portal.server.common.core.base.service.IBaseService;
import org.funcode.portal.server.common.domain.ielts.Storage;
import org.springframework.web.multipart.MultipartFile;
import org.funcode.portal.server.module.ielts.storage.domain.vo.StorageAddOrEditVo;

/**
* @author 李冲
Expand All @@ -19,8 +19,10 @@ public interface IStorageService extends IBaseService<Storage, Long> {
/**
* 上传文件
*
* @param file 文件
* @param storageAddOrEditVo 参数
* @return 上传结果
*/
Boolean upload(MultipartFile file);
Boolean upload(StorageAddOrEditVo storageAddOrEditVo);

Boolean deleteStorage(Long storageId);
}
Loading

0 comments on commit a8c0786

Please sign in to comment.