vue thinkphp实现腾讯云对象存储COS图片上传

  • 环境:
    thinkphp6
    vue2
    vant2.12
  • composer安装qcloud-sts-sdk
composer require qcloud_sts/qcloud-sts-sdk
  • 获取COS临时id、key的sts接口
<?php
declare (strict_types = 1);

namespace app\index\controller;
use QCloud\COSSTS\Sts;

class CosController
{

    //http://localhost:8516/index/cos/sts
    public function sts() {
        $sts = new Sts();
        $config = array(
            'url' => 'https://sts.tencentcloudapi.com/', // url和domain保持一致
            'domain' => 'sts.tencentcloudapi.com', // 域名,非必须,默认为 sts.tencentcloudapi.com
            'proxy' => '',
            'secretId' => 'xxxx', // 固定密钥,若为明文密钥,请直接以'xxx'形式填入,不要填写到getenv()函数中
            'secretKey' => 'xxxx', // 固定密钥,若为明文密钥,请直接以'xxx'形式填入,不要填写到getenv()函数中
            'bucket' => 'test-1253653367',//'test-1253653367', // 换成你的 bucket
            'region' => 'ap-shanghai', // 换成 bucket 所在园区
            'durationSeconds' => 1800, // 密钥有效期
            'allowPrefix' => array('2024/msc2024/*'), // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径,例子: a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用)
            // 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
            'allowActions' => array (
                // 简单上传
                'name/cos:PutObject',
                'name/cos:PostObject',
                // 分片上传
                'name/cos:InitiateMultipartUpload',
                'name/cos:ListMultipartUploads',
                'name/cos:ListParts',
                'name/cos:UploadPart',
                'name/cos:CompleteMultipartUpload'
            ),
            // 临时密钥生效条件,关于condition的详细设置规则和COS支持的condition类型可以参考 https://cloud.tencent.com/document/product/436/71306
            // "condition" => array(
            //     "ip_equal" => array(
            //         "qcs:ip" => array(
            //             "10.217.182.3/24",
            //             "111.21.33.72/24",
            //         )
            //     )
            // )
        );

        $tempKeys = $sts->getTempKeys($config);
        //echo json_encode($tempKeys);
        return json($tempKeys);

        // try {
        //     // 可能抛出异常的代码
        //     // 获取临时密钥,计算签名
        //     $tempKeys = $sts->getTempKeys($config);
        //     //echo json_encode($tempKeys);
        //     return json($tempKeys);
        // } catch (\Throwable $e) {
        //     // 异常处理代码
        //     return json(array('code'=>101, 'msg'=>$e->getMessage()));
        // }
    }
}

前端vue2代码,使用vant的文件上传组件

<van-uploader :after-read="handleUpload"></van-uploader>
data: {
  process: 0,
  isProcessVisible: false,
  uploadType: null, //1人像 2国徽 3自拍
  cos: null
}
handleUpload: function (res) {
  var file = res.file
  var that = this
  var that = this
  var cosBucket = 'test-123456'
  var cosRegion = 'ap-shanghai'
  var cosPrefix = '2024/msc2024'
  let name = file.name
  let size = file.size
  let ext = getFilePointExtName(name)
  let shortName = getFileName(name)
  let fileName = 'upload/' + getStrDateNoLine(new Date()) + "/" + uuid() + ext
  let fileKey = cosPrefix + '/' + fileName

  if(ext!= '.jpg' && ext!= '.JPG' && ext!= '.png' && ext!= '.PNG') {
    //this.$Message.error('请上传jpg格式文件');
    vant.Toast('请上传jpg或png格式文件');
    return
  }

  if(size > 1024*1024*2) {
    vant.Toast('图片文件不要大于2M');
    return
  }
  //alert(fileName)
  //console.log(file)
  if(this.cos == null) {
    this.cos = new COS({
      // getAuthorization 必选参数
      getAuthorization: function (options, callback) {
        // 初始化时不会调用,只有调用 cos 方法(例如 cos.putObject)时才会进入
        // 异步获取临时密钥
        // 服务端 JS 和 PHP 例子:https://github.com/tencentyun/cos-js-sdk-v5/blob/master/server/
        // 服务端其他语言参考 COS STS SDK :https://github.com/tencentyun/qcloud-cos-sts-sdk
        // STS 详细文档指引看:https://cloud.tencent.com/document/product/436/14048
        const url = '/index/cos/sts'; // url 替换成您自己的后端服务
        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) {
            }
            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();
      }
    });
  }

  // var cos = new COS({
  //   SecretId: 'xx',
  //   SecretKey: 'xx',
  // });
  that.isProcessVisible = true
  that.process = 0
  this.cos.uploadFile({
    Bucket: cosBucket, /* 填写自己的bucket,必须字段 */
    Region: cosRegion,     /* 存储桶所在地域,必须字段 */
    Key: fileKey,              /* 存储在桶里的对象键(例如:1.jpg,a/b/test.txt,图片.jpg)支持中文,必须字段 */
    Body: file, // 上传文件对象
    SliceSize: 1024 * 1024 * 5,     /* 触发分块上传的阈值,超过5MB使用分块上传,小于5MB使用简单上传。可自行设置,非必须 */
    onProgress: function(progressData) {
      //console.log(JSON.stringify(progressData));
      that.process = Math.floor(progressData.percent*100)
    }
  }, function(err, data) {
    that.isProcessVisible = false
    if (err) {
      console.log('上传失败', err);
    } else {
      console.log('上传成功');
      console.log('http://' + data.Location)
        var url = 'http://' + data.Location.replace("xxxx.cos.ap-shanghai.myqcloud.com", "cdn.xxx.xxx.com")
      console.log(url)
    }
  });
  return false
},
  • 用到的其它方法
function getFileName(fileName) {
  let pos = fileName.indexOf(".")
  if(pos >= 0) {
    return fileName.substr(0, pos)
  }
  return fileName
}

function getFileExtName(fileName) {
  let pos = fileName.indexOf(".")
  if(pos >= 0) {
    return fileName.substr(pos+1)
  }
  return ''
}

function getFilePointExtName(fileName) {
  var ext = getFileExtName(fileName)
  if(ext != '') {
    return '.' + ext
  }
  return ''
}

function getStrDateNoLine(date) {
  var y = date.getFullYear();
  var m = date.getMonth() + 1;//获取当前月份的日期 
  var d = date.getDate();
  if (m < 10) {
    m = '0' + m;
  }
  if (d < 10) {
    d = '0' + d;
  }
  return y + "" + m + "" + d;
}

//用于生成uuid
function S4() {
  return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}

function uuid() {
  return (S4() + S4() + "" + S4() + "" + S4() + "" + S4() + "" + S4() + S4() + S4());
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容