栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Iview+Vue+Springboot上传文件到腾讯COS

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Iview+Vue+Springboot上传文件到腾讯COS

上传文件
  • 前言
  • 前端
    • 上传组件
  • 后端
  • 附:腾讯COS专用工具类
  • 吐槽

前言

这个功能吧,我想了很久。以前用一个很蠢的方案实现过,但是不够优雅漂亮。哎,你猜怎么着,我最近琢磨出了一个比较靠谱的套路。走着

前端 上传组件

  

1.点击或将文件拖拽到这里

其中saveAction是后端对应的接口地址,比如/img/upload。:data则是访问时带的参数,accept规定可用文件类型。
比较关键的是before-upload这个方法,它会阻断上传的过程,转而成为手动,这样的好处是如果上传的这个文件你想换,就可以手动删掉重新选

// 获取真实文件,.name是文件原始名称
beforeUpload(file) {
  this.files = file
  this.currentFileName = file.name
  return false
},

删除部分

{{ files.name }}

对应的js

removeItem() {
  this.files = null
},

最终上传:


对应的js

/confirm/iUpload() {
  this.$Modal./confirm/i({
    title: '确定提交吗?',
    onOk: () => {
      this.$refs.uploadImage.post(this.files)
    },
    onCancel: () => {
      this.$Message.warning('已取消')
    },
  })
},

这里我就要吹一下自己了,翻阅源码时发现iview原本的上传就是用内置的ajax的post方法实现的,这里我直接跳过了源码的封装,把post拿出来用,效果还不错~

后端

后端我琢磨了挺久,一直没找到特别好的办法。主要是我原本的思路是把file作为一个完整的文件传上去,但是后来我发现COS的源码里可以接受输入流,一下子反应过来可以把文件转成InputStream再上传,一下子优雅了很多:

@ApiOperation(value = "上传图片")
@PostMapping("/uploadImage/{creator}")
public ApiReturn uploadHeadImage(
        @RequestParam(value = "file") MultipartFile file,
        @PathVariable String creator,
        @RequestParam String filename
) {
    byte[] bytes;
    try {
    	// 把文件转成byte数组
        bytes = file.getBytes();
    } catch (Exception e) {
        log.error("Upload file error", e);
        return new ApiReturn<>(e.getMessage());
    }
    // 再把byte数组转成输入流
    InputStream uploadStream = new ByteArrayInputStream(bytes);
    URL url = null;
    try {
    	// 这里调用了我自己编写的COS工具,下面会写
        url = cosUtil.saveFile(filename, uploadStream);
    } catch (Exception e) {
        log.error(e.getMessage());
        return new ApiReturn<>(e.getMessage());
    }
    // 如果上传成功,把url落表,如果落表失败,把云上的图也删掉
    if (url != null) {
        int count = blackService.saveImage(ImageRecord.builder()
                .url(url.toString())
                .name(filename)
                .creator(StringUtils.hasText(creator) ? creator : "")
                .createTime(new Date())
                .build());
        if (count == 0) {
            // 存储失败,把云服务中的该图片删除
            cosUtil.delFile(filename);
            return new ApiReturn<>("未知原因存储失败");
        }
    }
    return new ApiReturn<>(url.toString());
}
附:腾讯COS专用工具类
@Component
@Slf4j
public class CosUtil {

    
    @Value("${cos.bucket-name}")
    private String bucketName;

    
    @Value("${cos.bucket}")
    private String bucket;

    
    @Value("${cos.bucket-position}")
    private String bucketPosition;

    
    @Value("${cos.secret-id}")
    private String secretId;

    
    @Value("${cos.secret-key}")
    private String secretKey;

    
    @Value("${cos.app-id}")
    private String appId;

    
    private TransferManager transferManager;

    
    private COSClient cosClient;

    
    @PostConstruct
    private void init() {
        log.info("初始化COS Client中,参数为: {}",
                String.format("bucketName: %s,appid: %s, bucket: %s", bucketName, appId, bucket));
        Region region = new Region(bucketPosition);
        cosClient = new COSClient(new BasicCOSCredentials(secretId, secretKey), new ClientConfig(region));
        createBucket();
        ExecutorService threadPool = getThreadPool();
        // 传入一个 threadpool, 若不传入线程池, 默认 TransferManager 中会生成一个单线程的线程池。
        transferManager = new TransferManager(cosClient, threadPool);
    }

    private void createBucket() {
        if (cosClient.listBuckets().size() == 0) {
            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
            // 设置 bucket 的权限为PublicRead(公有读私有写)
            createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
            try {
                cosClient.createBucket(createBucketRequest);
            } catch (CosClientException serverException) {
                serverException.printStackTrace();
            }
        }
    }

    private ExecutorService getThreadPool() {
        return new ThreadPoolExecutor(
                Runtime.getRuntime().availableProcessors(),
                200,
                0L,
                TimeUnit.MILLISECONDS,
                new linkedBlockingQueue<>(1024),
                new ThreadFactoryBuilder()
                        .setNameFormat("demo-pool-%d").build(),
                new ThreadPoolExecutor.AbortPolicy()
        );
    }

    
    public URL saveFile(String key, File file) throws InterruptedException {
        transferManager.upload(
                new PutObjectRequest(bucketName, String.format("%s/%s", bucket, key), file)
        ).waitForUploadResult();
        // 关闭 TransferManger
        transferManager.shutdownNow();
        return cosClient.generatePresignedUrl(bucketName, String.format("%s/%s", bucket, key),
                new Date(System.currentTimeMillis() + 5 * 60 * 10000));
    }

    
    public URL saveFile(String key, InputStream inputStream) throws InterruptedException, ParseException {
        Objectmetadata objectmetadata = new Objectmetadata();
        objectmetadata.setExpirationTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2030-01-01 23:59:59"));
        transferManager.upload(bucketName,
                String.format("%s/%s", bucket, key),
                inputStream, objectmetadata).waitForUploadResult();
        return cosClient.generatePresignedUrl(bucketName, String.format("%s/%s", bucket, key),
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2030-01-01 23:59:59"));
    }

    
    public COSObject getCosObject(String key) {
        return cosClient.getObject(bucketName, key);
    }

    
    public boolean ifImageExist(String key) {
        return cosClient.doesObjectExist(bucketName, String.format("%s/%s", bucket, key));
    }

    
    public URL getUpdateFileUrl(String key) {
        return cosClient.generatePresignedUrl(bucketName, String.format("%s/%s", bucket, key),
                new Date(System.currentTimeMillis() + 31104 * 1000000L));
    }

    
    public void delFile(String key) {
        cosClient.deleteObject(bucketName, String.format("%s/%s", bucket, key));
    }
}
吐槽

腾讯COS的文档真的不大靠谱,如果你想自己写工具类,强烈建议对照源码找API,不要用文档的API。
本文首发于CSDN,作者:亭台烟雨中

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/318720.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号