上一篇讲了如何通过 Web 直传文件到 COS,在其基础上介绍上传后如何下载文件
后端 STS 服务 首先后端的 STS 服务需要改造一下,增加查询下载 URL 的权限
{ Action: []string{ // 下载操作 "name/cos:GetObject", }, Effect: "allow", Resource: []string{ "qcs::cos:ap-guangzhou:uid/" + appId + ":" + bucket + "/*", }, Condition: map[string]map[string]interface{}{}, }, 其他权限列表请可以看:
COS API 授权策略使用指引
访问策略生效条件
前端 Demo 改造 参考Javascript SDK,上传后通过 SDK 得到访问 URL,可以在页面展示或者下载
<template> <div> <div> <input type="file" @change="uploadImage" ref="imageInput" /> <button @click="submitImage">Upload Image</button> <button v-if="imageUrl" @click="downloadImage">Download Image</button> </div> <div> <img v-if="imageUrl" :src="imageUrl" alt="Description of image "> </div> </div> </template> <script> import COS from 'cos-js-sdk-v5'; const bucket = ${bucket}; const region = ${region}; export default { data() { return { imageFile: null, cos: null, imageUrl: null, imageKey: null, tmpSecretId: "", tmpSecretKey: "", sessionToken: "", }; }, methods: { uploadImage(event) { this.imageFile = event.target.files && event.target.files[0]; }, submitImage() { if (!this.imageFile) { alert("Please choose an image to upload."); return; } this.initCOS(); this.uploadToCOS(); }, initCOS() { this.cos = new COS({ getAuthorization: function (options, callback) { const url = 'http://${host}:8080/credentials' const xhr = new XMLHttpRequest() let data = null let credentials = null xhr.open('GET', url, true) xhr.onload = function (e) { try { data = JSON.parse(e.target.responseText); credentials = data.credentials; } catch (e) { console.log(e) } if (!data || !credentials) { return console.error('credentials invalid:\n' + JSON.stringify(data, null, 2)) } callback({ TmpSecretId: credentials.tmpSecretId, TmpSecretKey: credentials.tmpSecretKey, SecurityToken: credentials.sessionToken, StartTime: data.startTime, // 时间戳,单位秒,如:1580000000 ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000000 }) } xhr.send(); } }) }, uploadToCOS() { const key = `test/${Date.now()}_${this.imageFile.name}`; this.cos.uploadFile( { Bucket: bucket, Region: region, Key: key, StorageClass: "STANDARD", Body: this.imageFile, }, (err) => { if (err) { console.error("Error uploading image:", err); alert("Error uploading image."); } else { this.imageKey = key; this.getImageUrl() alert("Image uploaded successfully."); this.$refs.imageInput.value = null; this.imageFile = null; } } ); }, getImageUrl() { let that = this this.cos.getObjectUrl({ Bucket: bucket, Region: region, Key: this.imageKey, }, function (err, data) { if (err) return console.log(err); /* 通过指定 response-content-disposition=attachment 实现强制下载 */ const downloadUrl = data.Url + (data.Url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment'; /* 可拼接 filename 来实现下载时重命名 */ /* downloadUrl += ';filename=myname'; */ // (推荐使用 window.open()方式)这里是新窗口打开 url,如果需要在当前窗口打开,可以使用隐藏的 iframe 下载,或使用 a 标签 download 属性协助下载 that.imageUrl = downloadUrl console.log("Image uploaded successfully. URL:", that.imageUrl); }) }, downloadImage() { const link = document.createElement("a"); link.href = this.imageUrl; link.download = this.imageUrl.split("/").pop(); link.click(); }, }, }; </script>