腾讯云cos对象存储服务文件上传api就是一个大坑

一、介绍


对象存储服务(Cloud Object Service)是基于腾讯多年海量服务经验,对外提供的可靠、安全、易用的海量存储服务。提供多样化接入方式,以及全国部署的上传加速集群,可以无缝衔接CDN进行加速下载。


二、cos 文件上传api源码


/**
	 * 单个文件上传,适用于小文件
	 * 
	 * @param bucketName
	 *            bucket名称
	 * @param remotePath
	 *            远程文件路径
	 * @param localPath
	 *            本地文件路径
	 * @return 服务器端返回的操作结果,成员code为0表示成功,具体参照文档手册
	 * @throws Exception
	 */
	public String uploadFile(String bucketName, String remotePath,
			String localPath) throws Exception {
		if (!FileProcess.isLegalFile(localPath)) {
			String errorMsg = localPath
					+ " is not file or not exist or can't be read!";
			LOG.error(errorMsg);
			JSONObject errorRet = new JSONObject();
			errorRet.put(ResponseBodyKey.CODE, ErrorCode.PARAMS_ERROR);
			errorRet.put(ResponseBodyKey.MESSAGE, errorMsg);
			return errorRet.toString();
		}
		FileInputStream localFileInputStream = null;
		try {
			localFileInputStream = FileProcess.getFileInputStream(localPath);
			return uploadFile(bucketName, remotePath, localFileInputStream);
		} catch (Exception e) {
			LOG.error("UploadFile {} occur a error {}", localPath, e.toString());
			throw e;
		} finally {
			FileProcess.closeFileStream(localFileInputStream, localPath);
		}
	}


三、为什么是个坑


从上面的代码中,我们可以看出,使用cos的文件上传接口,我们需要指定远程文件地址(就是我们需存储到cos的那个目录下的那个文件比如/folder/1.txt)和本地文件路径。下面我用三点来说为什么是个坑

1.在实际的开发中,很多时候,我们上传文件到web后端,在controller中以file对象存在,像spring mvc 的MultipartFile 对象是不容易获取到服务器缓存该文件的路径;

2.在手机app上传文件,app通常会采用http的方式把文件以字节数组的方式传到后台服务的,莫非还需要们在后台服务缓存一下;

3.在分布式系统中一般会把文件操作放在一个专门提供上传下载的分布式服务中比如采用dubbo,在这种方式下,一般采用字节或者采用BASE64Decoder转化成字符串来传送文件内容,如果采用cos自己原有的接口,还需要缓存一下文件。

     综上所述,cos原有的接口就是一个坑,根本不实用。那么有什么好的解决方法呢,请继续往下面看。


四,解决方法


在api中自己定义了一个扩展方法,把最后的localpath改为接收字节数组,代码如下:


/**
	 * 流文件上传,适用于小文件,自定义扩展方法
	 * 
	 * @param bucketName
	 *            bucket名称
	 * @param remotePath
	 *            远程文件路径
	 * @param fileContent
	 *            文件字节数组
	 * @return 服务器端返回的操作结果,成员code为0表示成功,具体参照文档手册
	 * @throws Exception
	 */
	public String uploadFileExt(String bucketName, String remotePath,
			byte[] fileContent) throws Exception {
		String url = getEncodedCosUrl(bucketName, remotePath);
		String shaDigest = CommonCodecUtils.getFileSha1(fileContent);


		HashMap<String, String> postData = new HashMap<String, String>();
		postData.put(RequestBodyKey.OP, RequestBodyValue.OP_UPLOAD);
		postData.put(RequestBodyKey.SHA, shaDigest);
		long expired = getExpiredTimeInSec();
		String sign = Sign.appSignature(appId, secretId, secretKey, expired,
				bucketName);


		HashMap<String, String> httpHeader = new HashMap<String, String>();
		httpHeader.put(RequestHeaderKey.Authorization, sign);


		return httpSender.sendFileRequest(url, httpHeader, postData,
				fileContent, timeOut);
	}


有需要的朋友只需把该方法,拷贝到CosCloud类当中就可以了。


五.把文件转化成字节数组方式


1、springmvc 上传controller中MultipartFile payfile文件参数获取成字节数组方式:


payfile.getBytes();//这个方法就可以获取字节数组



2、将file文件转化成字节数组方式


public static byte[] getByte(File file) throws Exception {
		byte[] bytes = null;
		if (file != null) {
			InputStream is = new FileInputStream(file);
			int length = (int) file.length();
			if (length > Integer.MAX_VALUE) // 当文件的长度超过了int的最大值
			{
				System.out.println("this file is max ");
				return null;
			}
			bytes = new byte[length];
			int offset = 0;
			int numRead = 0;
			while (offset < bytes.length
					&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
				offset += numRead;
			}
			// 如果得到的字节长度和file实际的长度不一致就可能出错了
			if (offset < bytes.length) {
				System.out.println("file length is error");
				return null;
			}
			is.close();
		}
		return bytes;
	}
}




注:非常大家浏览这篇文章,如果有什么不懂的或者有错的地方请大家多多指教,谢谢!
 
<think>我们正在使用SpringBoot整合腾讯云COS对象存储实现文件上传功能。根据提供的引用内容,我们需要进行以下步骤:1.开通腾讯云对象存储服务,并获取SecretId、SecretKey、存储桶名称(Bucket)、地域(Region)以及请求域名(URL)。2.在SpringBoot项目中引入腾讯云COS的JavaSDK依赖。3.配置腾讯云COS的相关参数(SecretId,SecretKey, Bucket名称,地域等)。4.编写文件上传的接口,使用COS客户端进行文件上传。具体步骤:第一步:开通腾讯云对象存储服务并获取密钥等信息-登录腾讯云控制台,进入对象存储COS服务,开通服务。-创建一个存储桶(Bucket),记录存储桶名称和所属地域。-在访问管理(CAM)中获取SecretId和SecretKey。第二步:在Spring Boot项目中添加依赖-在pom.xml中添加腾讯云COS JavaSDK依赖:```xml<dependency><groupId>com.qcloud</groupId><artifactId>cos_api</artifactId><version>5.6.54</version></dependency>```第三步:配置application.yml(或application.properties)-根据引用[2]中的配置示例,在application.yml中配置腾讯云COS参数:```yamltencent:cos:secretId: your-secret-id#替换为你的SecretIdsecretKey:your-secret-key#替换为你的SecretKeybucketName:your-bucket-name#存储桶名称region: ap-shanghai#存储桶所在地域url:https://your-bucket-name.cos.ap-shanghai.myqcloud.com #请求域名,根据实际情况修改```第四步:创建配置类读取配置(可选,也可以直接在Service中注入)-可以创建一个配置类来读取这些配置,例如:```java@Configurationpublicclass CosConfig {@Value("${tencent.cos.secretId}")privateString secretId;@Value("${tencent.cos.secretKey}")privateString secretKey;@Value("${tencent.cos.bucketName}")privateString bucketName;@Value("${tencent.cos.region}")private Stringregion;@Value("${tencent.cos.url}")privateString url;//生成COSClient@BeanpublicCOSClient cosClient(){COSCredentialscred =new BasicCOSCredentials(secretId,secretKey);ClientConfig clientConfig =new ClientConfig(newRegion(region));returnnew COSClient(cred, clientConfig);}//也可以将其他配置作为Bean注入,方便使用public StringgetBucketName(){return bucketName;}publicString getUrl() {returnurl;}}```第五步:编写文件上传服务-创建一个Service类,用于文件上传操作。```java@Servicepublic classCosService{@Autowiredprivate COSClientcosClient;@Autowiredprivate CosConfig cosConfig;publicString uploadFile(MultipartFilefile,String fileName) {try{//获取存储桶名称String bucketName =cosConfig.getBucketName();//指定文件在存储桶中的路径(可以按需修改)String key= "/" +fileName;//例如直接放在根目录下//将文件转换为输入流InputStreaminputStream= file.getInputStream();//创建上传对象ObjectMetadataobjectMetadata =new ObjectMetadata();//设置输入流长度objectMetadata.setContentLength(file.getSize());//上传文件PutObjectRequest putObjectRequest= newPutObjectRequest(bucketName, key, inputStream,objectMetadata);cosClient.putObject(putObjectRequest);//返回文件的访问URL(需要拼接)returncosConfig.getUrl() +key;}catch (Exception e) {e.printStackTrace();returnnull;}}}```第六步:编写Controller接口-创建一个Controller,提供文件上传的接口。```java@RestController@RequestMapping("/file")public classFileController{@Autowiredprivate CosService cosService;@PostMapping("/upload")public BaseResponse<String> uploadFile(@RequestParam("file") MultipartFilefile){if (file.isEmpty()) {returnResultUtils.error(400,"文件为空");}//生成文件名(可以使用UUID避免重复)StringoriginalFilename= file.getOriginalFilename();StringfileName =UUID.randomUUID().toString()+ originalFilename.substring(originalFilename.lastIndexOf("."));//上传文件Stringurl =cosService.uploadFile(file, fileName);if (url !=null){return ResultUtils.success(url);}else {returnResultUtils.error(500,"文件上传失败");}}}```注意:这里使用了引用[3]中的BaseResponse和ResultUtils来统一返回格式。第七步:测试-启动项目,使用Postman或前端页面上传文件,查看返回的文件URL。安全建议:-敏感信息(SecretId和SecretKey)不要直接写在配置文件中,建议使用配置中心或环境变量。相关问题:1.如何设置文件上传COS的指定目录?-在`uploadFile`方法中,修改key的值,例如:`Stringkey ="images/"+ fileName;`,则文件会上传到存储桶的images目录下。2.如何限制上传文件的类型和大小?-可以在Controller中添加校验,或者使用Spring Boot的配置限制文件大小(在application.yml中配置`spring.servlet.multipart.max-file-size`和`max-request-size`)。3.如何实现文件下载和删除?-参考腾讯云COS SDK文档,使用`COSClient`的`getObject`方法下载文件,使用`deleteObject`方法删除文件。4.如何避免文件名冲突?-使用UUID生成新的文件名,如示例所示。5.如何保证上传的安全性?-使用临时密钥(STS)进行临时授权,避免直接使用永久密钥。以上即为使用Spring Boot整合腾讯云COS对象存储实现文件上传的基本步骤。</think>### 使用腾讯云COS实现文件上传的步骤 #### 1. **准备工作** - 开通腾讯云COS服务并创建存储桶 - 获取以下关键信息: - `SecretId`:访问密钥ID - `SecretKey`:访问密钥 - `BucketName`:存储桶名称(如 `example-bucket-1250000000`) - `Region`:存储桶地域(如 `ap-shanghai`) - 在腾讯云控制台完成存储桶权限配置[^1] #### 2. **Spring Boot项目配置** ##### (1) 添加依赖 ```xml <!-- pom.xml --> <dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>5.6.89</version> </dependency> ``` ##### (2) 配置参数 ```yaml # application.yml tencent: cos: secretId: your-secret-id # 替换为实际值 secretKey: your-secret-key bucketName: your-bucket-name region: ap-shanghai ``` #### 3. **核心代码实现** ##### (1) COS工具类 ```java @Component public class CosClient { @Value("${tencent.cos.secretId}") private String secretId; @Value("${tencent.cos.secretKey}") private String secretKey; @Value("${tencent.cos.bucketName}") private String bucketName; @Value("${tencent.cos.region}") private String region; // 获取COS客户端实例 public COSClient getCosClient() { COSCredentials cred = new BasicCOSCredentials(secretId, secretKey); Region region = new Region(this.region); ClientConfig config = new ClientConfig(region); return new COSClient(cred, config); } // 获取存储桶名称 public String getBucketName() { return bucketName; } } ``` ##### (2) 文件上传服务 ```java @Service public class FileUploadService { @Autowired private CosClient cosClient; public String uploadFile(MultipartFile file) { try { COSClient client = cosClient.getCosClient(); String fileName = generateFileName(file.getOriginalFilename()); // 创建上传请求 PutObjectRequest request = new PutObjectRequest( cosClient.getBucketName(), fileName, file.getInputStream(), new ObjectMetadata() ); // 执行上传 client.putObject(request); client.shutdown(); // 返回文件访问URL return "https://" + cosClient.getBucketName() + ".cos." + cosClient.getRegion() + ".myqcloud.com/" + fileName; } catch (Exception e) { throw new RuntimeException("上传失败: " + e.getMessage()); } } // 生成唯一文件名 private String generateFileName(String originalName) { return UUID.randomUUID() + originalName.substring(originalName.lastIndexOf(".")); } } ``` ##### (3) 控制器接口 ```java @RestController @RequestMapping("/api/file") public class FileController { @Autowired private FileUploadService uploadService; @PostMapping("/upload") public BaseResponse<String> upload(@RequestParam("file") MultipartFile file) { if (file.isEmpty()) { return ResultUtils.error(400, "文件不能为空"); } try { String url = uploadService.uploadFile(file); return ResultUtils.success(url); } catch (Exception e) { return ResultUtils.error(500, e.getMessage()); } } } ``` #### 4. **测试上传** 使用Postman发送 **multipart/form-data** 请求: ``` POST /api/file/upload Body: file=[选择文件] ``` 成功响应示例: ```json { "code": 0, "data": "https://example-bucket-1250000000.cos.ap-shanghai.myqcloud.com/3c7d8f90-a2b3.jpg", "message": "ok" } ``` #### 5. **安全建议** 1. 前端直传:使用临时密钥STS方案,避免暴露永久密钥[^2] 2. 文件校验: - 在服务端验证文件类型(如通过`file.getContentType()`) - 限制文件大小(Spring Boot配置`spring.servlet.multipart.max-file-size`) 3. 权限控制:在COS控制台设置Bucket访问策略为**私有读写** ### 常见问题解决 - **权限错误403**:检查SecretId/SecretKey是否正确,存储桶权限是否开启写入 - **连接超时**:确认服务器网络可访问`cos.${region}.myqcloud.com` - **大文件上传**:使用分块上传接口(`TransferManager`类) > 完整示例代码参考腾讯云官方文档:[Java SDK 使用指南](https://cloud.tencent.com/document/product/436/10199)[^3]
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值