(亲测有效)SpringBoot项目集成腾讯云COS对象存储(2)

接上文(亲测有效)SpringBoot项目集成腾讯云COS对象存储(1)-CSDN博客

目录

3、通用能力类

文件下载

测试


3、通用能力类

文件下载

官方文档介绍了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 获取存储信息.

java 复制代码
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 对象中。

注意要设置文件下载专属的响应头。同上,测试接口一定要加上管理员权限!防止任何用户随意上传文件。

测试文件下载接口代码如下:

java 复制代码
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这个文件下载的请求返回成功了。没报错,但就是不知道为什么图片不显示。

至此,后端操作对象存储的代码已编写完成。

相关推荐
抓哇小菜鸡7 分钟前
WebSocket
java·websocket
single59411 分钟前
【c++笔试强训】(第四十五篇)
java·开发语言·数据结构·c++·算法
Q_192849990618 分钟前
基于Spring Boot的电影网站系统
java·spring boot·后端
豌豆花下猫31 分钟前
Python 潮流周刊#83:uv 的使用技巧(摘要)
后端·python·ai
ZStack开发者社区31 分钟前
青岛市勘察测绘研究院携手云轴科技ZStack获评专有云典型案例
云计算
凡人的AI工具箱37 分钟前
每天40分玩转Django:Django部署概述
开发语言·数据库·后端·python·django
老鑫安全培训44 分钟前
从安全角度看 SEH 和 VEH
java·网络·安全·网络安全·系统安全·安全威胁分析
罗政1 小时前
PDF书籍《手写调用链监控APM系统-Java版》第8章 插件与链路的结合:Gson插件实现
java·pdf·linq
SomeB1oody1 小时前
【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字
开发语言·后端·rust
SomeB1oody1 小时前
【Rust自学】7.3. 路径(Path)Pt.2:访问父级模块、pub关键字在结构体和枚举类型上的使用
开发语言·后端·rust