赞
踩
目录
官方文档介绍了2种文件下载方式。一种是直接下载 COS 的文件到后端服务器(适合服务器端处理文件),另一种是获取到文件下载输入流(适合返回给前端用户)。
- 参考官方文档:
- · https://cloud.tencent.com/document/product/436/65937
- · https://cloud.tencent.com/document/product/436/10199#.E4.B8.8B.E8.BD.BD.E5.AF.B9.E8.B1.A1
其实还有第三种"下载方式”,直接通过路径链接访问,适用于单一的、可以被用户公开访问的资源,比如用户头像、代码生成器文件。
但是对于代码生成器产物包文件,更建议通过后端服务器从COS下载文件并返回给前端,这样可以在后端限制只有登录用户才能下载。
(1)首先在 CosManager 中新增对象下载方法getObject(),根据对象的 key 获取存储信息.
- import com.qcloud.cos.COSClient;
- import com.qcloud.cos.model.COSObject;
- import com.qcloud.cos.model.GetObjectRequest;
- import com.qcloud.cos.model.PutObjectRequest;
- import com.qcloud.cos.model.PutObjectResult;
- import com.waterai.water.config.CosClientConfig;
- import java.io.File;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Component;
-
- /**
- * Cos 对象存储操作
- */
- @Component
- public class CosManager {
-
- @Resource
- private CosClientConfig cosClientConfig;
-
- @Resource
- private COSClient cosClient;
-
- /**
- * 上传对象
- * @param key 唯一键
- * @param localFilePath 本地文件路径
- * @return
- */
- public PutObjectResult putObject(String key, String localFilePath) {
- PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key, new File(localFilePath));
- return cosClient.putObject(putObjectRequest);
- }
-
- /**
- * 上传对象
- * @param key 唯一键
- * @param file 文件
- * @return
- */
- public PutObjectResult putObject(String key, File file) {
- PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key, file);
- return cosClient.putObject(putObjectRequest);
- }
-
- /*
- * 下载对象
- * @param key 唯一键
- * @return
- * */
- public COSObject getObject(String key) {
- GetObjectRequest getObjectRequest = new GetObjectRequest(cosClientConfig.getBucket(), key);
- return cosClient.getObject(getObjectRequest);
- }
- }
(1)为了方便测试,在 FileController 中编写测试文件下载接口。
核心流程是根据路径获取到COS 文件对象,然后将文件对象转换为文件流,并写入到 Servlet的Response 对象中。
注意要设置文件下载专属的响应头。同上,测试接口一定要加上管理员权限!防止任何用户随意上传文件。
测试文件下载接口代码如下:
- import cn.hutool.core.io.FileUtil;
- import com.waterai.water.annotation.AuthCheck;
- import com.waterai.water.common.BaseResponse;
- import com.waterai.water.common.ErrorCode;
- import com.waterai.water.common.ResultUtils;
- import com.waterai.water.constant.FileConstant;
- import com.waterai.water.constant.UserConstant;
- import com.waterai.water.exception.BusinessException;
- import com.waterai.water.manager.CosManager;
- import com.waterai.water.model.dto.file.UploadFileRequest;
- import com.waterai.water.model.entity.User;
- import com.waterai.water.model.enums.FileUploadBizEnum;
- import com.waterai.water.service.UserService;
- import java.io.File;
- import java.util.Arrays;
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletRequest;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.RandomStringUtils;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestPart;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.multipart.MultipartFile;
-
- /**
- * 文件接口
- */
- @RestController
- @RequestMapping("/file")
- @Slf4j
- public class FileController {
- @Resource
- private UserService userService;
-
- @Resource
- private CosManager cosManager;
-
- /*
- * 其他方法。。。。。
- * */
-
- /*
- * 测试文件上传
- * */
- @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
- @PostMapping("/test/upload")
- public BaseResponse<String> testUploadFile(@RequestPart("file") MultipartFile multipartFile) {
- // 文件目录
- String filename = multipartFile.getOriginalFilename();
- String filepath = String.format("/test/%s", filename);
- File file = null;
- try {
- //上传文件
- file = File.createTempFile(filepath, null);
- multipartFile.transferTo(file);
- cosManager.putObject(filepath, file);
- //返回可访问地址
- return ResultUtils.success(filepath);
- } catch (Exception e) {
- System.out.println("file upload error, filepath = " + filepath + ", error = " +e);
- throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败");
- } finally {
- if (file != null) {
- //删除临时文件
- boolean delete = file.delete();
- if (!delete) System.out.println("file delete error, filepath = [l" + filepath);
- }
- }
- }
-
- /*
- * 测试文件下载
- */
- @AuthCheck (mustRole = UserConstant.ADMIN_ROLE)
- @GetMapping("/test/download/")
- public void testDownloadFile(String filepath, HttpServletResponse response) throws IOException {
- COSObjectInputStream cosObjectInput = null;
- try {
- COSObject cosObject = cosManager.getObject(filepath);
- cosObjectInput = cosObject.getObjectContent();
- //处理下载到的流
- byte[] bytes = IOUtils.toByteArray(cosObjectInput);
- //设置响应头
- response.setContentType("application/octet-stream;charset=UTF-8");
- response.setHeader("Content-Disposition", "attachment; filename=" + filepath);
- //写入响应
- response.getOutputStream().write(bytes);
- response.getOutputStream().flush();
- } catch (Exception e) {
- log.error("file download error, filepath = " + filepath, e);
- throw new BusinessException(ErrorCode.SYSTEM_ERROR, "下载失败");
- } finally {
- if (cosObjectInput != null) cosObjectInput.close();
- }
- }
- }
(2)修改启动配置李的active profiles,使用local配置启动项。
然后点击启动按钮启动项目。
(3)打开 Swagger接口文档,此处我的项目端口是8101,因此就是http://localhost:8101/api/doc.html,然后在file-controller中找到测试文件上传的这个接口,开始进行测试。
首先,点击选择文件,从本地选择一个文件,然后点击发送请求。
就可以看到5.jpg这个文件下载的请求返回成功了。没报错,但就是不知道为什么图片不显示。
至此,后端操作对象存储的代码已编写完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。