主页

fastadmin上传文件至阿里云OSS

看尽落尘花   IP属地: 青海
0 点赞 0阅读 1151
首先需要在阿里云开通存储对象(OSS),代码里包含了阿里云的视频点播处理

后端代码:


<?php

namespace app\admin\controller\auth;

use app\common\controller\Backend;
use Mts\Request\V20140618 as Mts;
use vod\Request\V20170321 as vod;
use Kms\Request\V20160120 as kms;
use OSS\OssClient;

// require_once VENDOR_PATH . '../extend/sts-server/aliyun-php-sdk-core/Config.php';
use Sts\Request\V20150401 as Sts;
/**
 * 规则管理
 *
 * @icon   fa fa-list
 * @remark 规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过控制台进行生成规则节点
 */
class Upload extends Backend
{

    /**
     * @var \app\admin\model\AuthRule
     */
    protected $model = null;
    protected $rulelist = [];
    protected $url = 'https://sts.aliyuncs.com';
   //RAM子账号下的accessKey(不要使用主账号创建)否则会报Roles may not be assumed by root accounts.错误
    protected $accessKeyId='xxxxx';
    protected $accessKeySecret = 'xxxxxxx';
	
    //一定要在OSS存储里设置跨域设置,并且允许所以访问请求,暴露header写
    //etag
     //x-oss-request-id
     //其他写*号,代表所以请求都能访问
    protected $roleArn="acs:ram::1968572159217379:role/oss";//指定角色的 ARN ,角色策略权限
    protected $roleSessionName = 'client';//用户自定义参数。此参数用来区分不同的 token,可用于用户级别的访问审计。格式:^[a-zA-Z0-9\.@\-_]+$
    protected $durationSeconds = '3600';//指定的过期时间
    private $accessVideoKeyId = 'xxxx';
    private $accessVideoKeySecret = 'xxxxx';
    private $regionVideoId = 'cn-beijing';    // 点播服务所在的Region,国内请填cn-shanghai,不要填写别的区域
    private $endpointVideo = 'oss-cn-beijing.aliyuncs.com';
    private $stsVideo  = null;
    protected $client = null;

    public function _initialize()
    {
        parent::_initialize();
        
    }

    /**
     * 查看
     */
    public function index()
    {
        if ($this->request->isAjax()) {
            $form = $this->request->post();
            $data = [
                'admin_id'=>1,
                'uploadtime'=>time(),
                'createtime'=>time(),
                'updatetime'=>time(),
                'filename'=>$form['filename'],
                'url'=>$form['fileurl'],
                'filesize'=>$form['filesize'],
                'mimetype'=>$form['mimetype'],
                'imagetype'=>$form['imagetype'],
                'storage'=>'cloud'
            ];
           
            $attachment = model('attachment')->save($data);
            $res = ['url'=>$form['fileurl']];
            
            $this->success('上传成功!','',$res);
           
            return json($attachment);
        }
        return $this->view->fetch();
    }
    //oss上传
    public function alists(){
        require_once VENDOR_PATH.'../extend/sts-server/aliyun-php-sdk-core/Config.php';
        $iClientProfile = \DefaultProfile::getProfile("cn-beijing", $this->accessKeyId, $this->accessKeySecret);
 
        $client = new \DefaultAcsClient($iClientProfile);
 
        $request = new \Sts\Request\V20150401\AssumeRoleRequest();
 
        $request->setRoleSessionName("client_name");
 
        $request->setRoleArn($this->roleArn);
 
        $request->setDurationSeconds($this->durationSeconds);
        $response = $client->doAction($request);
 
        $rows = array();
 
        $body = $response->getBody();
 
        $content = json_decode($body);
        
        if ($response->getStatus() == 200){
            $rows['statusCode'] = 200;
            $rows['accessKeyId'] = $content->Credentials->AccessKeyId;
            $rows['accessKeySecret'] = $content->Credentials->AccessKeySecret;
            $rows['expiration'] = $content->Credentials->Expiration;
            $rows['securityToken'] = $content->Credentials->SecurityToken;
        }else{
            $rows['statusCode'] = 500;
            $rows['errorCode'] = $content->Code;
            $rows['errorMessage'] = $content->Message;
        }
        return json_encode($content);
        // $rows
        print_r($rows);
    }

    public function video_demand_upload($fileName=''){
        if ($this->request->isAjax()) {
            $info = [
                'title'=>time().'.mp4',
                'filename'=>time().'.mp4',
                'desc'=>'1',
            ];
            if($fileName){
                $info['title'] = $fileName;
                $info['filename'] = $fileName;
            }
            return $this->create_upload_video($info);
        }
        
        return $this->view->fetch();
    }
    /**
     * @desc [获取上传地址和凭证/上传到视频点播服务]
     * @param  [type] $client [description]
     * @param array $fileInfo = array();
     * @return [type]         [description]
     */
    private function create_upload_video($fileInfo)
    {
        require_once VENDOR_PATH . '../extend/aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php';
        try {
            $this->init_vod_client($this->accessVideoKeyId, $this->accessVideoKeySecret);
        } catch (\Exception $e) {
            print $e->getMessage();
            exit();
        }
        $request = new vod\CreateUploadVideoRequest();

        $request->setTitle($fileInfo['title']);        // 视频标题(必填参数)
        $request->setFileName($fileInfo['filename']); // 视频源文件名称,必须包含扩展名(必填参数)
        $request->setDescription($fileInfo['desc']);  // 视频源文件描述(可选)
        //转码模板ID
        $request->setTemplateGroupId("2cab6fbdeac04425d80ee87657f4bb8c");
        $request->setAcceptFormat('JSON');
        $res = $this->client->getAcsResponse($request);
        
        if(empty($res->VideoId)){
            $this->error('上传失败!');
        }
        model('Videotask')->save(['video_id'=>$res->VideoId]);
      
        return $res;
    }
    
     /**
     * @desc 刷新视频上传凭证
     * @param  [type] $client  [description]
     * @param  [type] $videoId [description]
     * @return [type]          [description]
     */
    public function refresh_upload_video($videoId)
    {
        try {
            $this->init_vod_client($this->accessVideoKeyId, $this->accessVideoKeySecret);
        } catch (\Exception $e) {
            print $e->getMessage();
            exit();
        }
        $request = new vod\RefreshUploadVideoRequest();
        $request->setVideoId($videoId);
        $request->setAcceptFormat('JSON');
        $res =  $this->client->getAcsResponse($request);
        return json($res);
    }
    /**
     * @desc 初始化客户端
     * @param  [type] $accessKeyId     [description]
     * @param  [type] $accessKeySecret [description]
     * @return [type]                  [description]
     */
    private function init_vod_client($accessKeyId, $accessKeySecret)
    {
        //初始化视频客户端
        $profile = \DefaultProfile::getProfile($this->regionVideoId, $accessKeyId, $accessKeySecret);
        $this->client = new \DefaultAcsClient($profile);
        //初始化sts授权策略客户端
        \DefaultProfile::addEndpoint($this->regionVideoId, $this->regionVideoId, "Sts", $this->endpointVideo);
        $iClientProfile = \DefaultProfile::getProfile($this->regionVideoId, $accessKeyId,  $accessKeySecret);
        $this->stsVideo = new \DefaultAcsClient($iClientProfile);
    }
}


html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>APP下载</title>
    <script src="/assets/img/app/jquery-3.4.1.min.js" language="javascript"> </script>
    <!-- <script src="/assets/libs/jquery/dist/jquery.min.js" language="javascript"> </script> -->
    <script src="/assets/libs/aliyun-upload-sdk/aliyun-oss-sdk-6.0.2.min.js"></script>
    <!-- <script src="http://gosspublic.alicdn.com/aliyun-oss-sdk-4.4.4.min.js"></script> -->
    <!-- <script src="/assets/libs/layui/layui.js"></script> -->
    <link rel="stylesheet" href="/assets/libs/layui/css/layui.css"  media="all">
</head>

<body>
   
    <div id="up_wrap"></div>
    <div class="form-group">
        <input type="file" id="file" multiple="multiple" />
    </div>
   <div class="msg" style="font-size:12px;color:red"></div>
    <div class="form-group" style="margin-top:20px">
        <!-- <input type="button" class="btn btn-primary" id="file-button" value="上传" /> -->
        <!-- <input type="button" class="btn btn-primary" id="Continue-button" value="Continue" /> -->
    </div>

    <script type="text/javascript">
        var appServer = 'auth/upload/alists';//获取ststoken的接口,这边这个地址是我本地的。你们的接口地址自己应该清楚
        var bucket = 'xxxx';
        var region = 'oss-cn-beijing';//前面新建bucket时选择过的。
        var uid = 'client';//用户标识。这个根据自己情况自己定
        var Buffer = OSS.Buffer;
        //获取授权STSToken,并初始化client
        var applyTokenDo = function (func) {
            var url = appServer;
            return $.get(url).then(function (result) {
                var res = JSON.parse(result);
                console.log(res);
                if(res.Message){
                    $('.msg').text(res.Message);
                    return;
                }
                var creds = res.Credentials;
                console.log(creds)
                var client = new OSS({
                    region: region,
                    stsToken: creds.securityToken,
                    secure:true,
                    accessKeyId: creds.AccessKeyId,
                    accessKeySecret: creds.AccessKeySecret,
                    stsToken: creds.SecurityToken,
                    bucket: bucket
                });
                return func(client);
            });
        };
     
        //上传文件
        var uploadFile = function (client) {
            if (upfiles.length < 1)
                return;
            upfile = upfiles[0];
            var file = upfile.file;
            // console.log(file)
            var size = file.size;
            var type = file.type;
            // console.log(upfile.name.split('.').splice(-1))
            var date = new Date();
            var month = date.getMonth()+1;
            var month = month < 10 ?  '0'  + month: month;
            var pathName = date.getFullYear()+''+month+''+date .getDate();
            var timestamp = (new Date()).valueOf();
            // console.log(pathName)
            // console.log(timestamp)
            //key可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
            // var key = upfile.name;
            var fielName = upfile.name.split('.').splice(-1)
            var key = 'uploads/'+pathName+'/'+timestamp+'.'+fielName[0];
            // console.log(key)
          
            var objkey = key + "_" + uid + ".json";
        //    console.log(client)
            return  client.multipartUpload(key, file, {
                progress: function (p, cpt, res) {
                    // console.log("p:", p);
                    // console.log("cpt:", cpt);
                    // console.log("res:", res);
                    if (cpt != undefined) {
                        var content = JSON.stringify(cpt);
                        client.put(objkey, new Buffer(content));
                    }
                    if(Math.floor(p * 100)==100){
                        var filePathUrl = "https://xxxxxx.oss-cn-beijing.aliyuncs.com/"+key;
                        Fast.api.ajax({
                            url:"auth/upload",
                            data:{fileurl:filePathUrl,filename:upfile.name,filesize:size,mimetype:type,imagetype:fielName[0]}
                        }, function(){
                            //成功的回调
                            Fast.api.close(filePathUrl)
                            console.log(111)
                        }, function(){
                            //失败的回调
                            console.log(222)
                        });
                    }
                    console.log(Math.floor(p * 100) + '%');
                    var bar = document.getElementById('progress-bar_' + upfile.num);
                    bar.style.width = Math.floor(p * 100) + '%';
                    bar.innerHTML = Math.floor(p * 100) + '%';
     
                }
            }).then(function (res) {
                console.log('upload success: ', res);
                upfiles.shift();
                client.delete(objkey);
                applyTokenDo(uploadFile);
            }).catch(function(err) {
                console.log(err);
                error(err);
            });
        };
     
        //断点续传文件
        var reUploadFile = function (client) {
            if (upfiles.length < 1)
                return;
            upfile = upfiles[0];
            var file = upfile.file;
            //key可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
            var key = upfile.name;
            var objkey = key + "_" + uid + ".json";
            return client.get(objkey).then(function (res) {
                var data = JSON.parse(res.content);
                data.file = file;
                return client.multipartUpload(key, file, {
                    checkpoint: data,
                    progress: function (p, cpt, res) {
                        console.log("p:", p);
                        console.log("cpt:", cpt);
                        if (cpt != undefined) {
                            var content = JSON.stringify(cpt);
                            client.put(objkey, new Buffer(content));
                        }
                        var bar = document.getElementById('progress-bar_' + upfile.num);
                        bar.style.width = Math.floor(p * 100) + '%';
                        bar.innerHTML = Math.floor(p * 100) + '%';
                    }
                }).then(function (ret) {
                    console.log('upload success:', ret);
                    upfiles.shift();
                    client.delete(objkey);
                    applyTokenDo(uploadFile);
                }).catch(function(err) {
                    console.log(err);
                    error(err);
                });
            });
        };
     
        function error(err){
            switch (err.status) {
                case 0:
                    if (err.name == "cancel") { //手动点击暂停上传
                        return;
                    }
                    break;
                case -1: //请求错误,自动重新上传
                    // 重新上传;
                    return;
                case 203: //回调失败
                    // 前端自己给后台回调;
                    return;
                case 400:
                    switch (err.code) {
                        case 'FilePartInterity': //文件Part已改变
                        case 'FilePartNotExist': //文件Part不存在
                        case 'FilePartState': //文件Part过时
                        case 'InvalidPart': //无效的Part
                        case 'InvalidPartOrder': //无效的part顺序
                        case 'InvalidArgument': //参数格式错误
                            // 清空断点;
                            // 重新上传;
                            return;
                        case 'InvalidBucketName': //无效的Bucket名字
                        case 'InvalidDigest': //无效的摘要
                        case 'InvalidEncryptionAlgorithmError': //指定的熵编码加密算法错误
                        case 'InvalidObjectName': //无效的Object名字
                        case 'InvalidPolicyDocument': //无效的Policy文档
                        case 'InvalidTargetBucketForLogging': //Logging操作中有无效的目标bucket
                        case 'MalformedXML': //XML格式非法
                        case 'RequestIsNotMultiPartContent': //Post请求content-type非法
                            // 重新授权;
                            // 继续上传;
                            return;
                        case 'RequestTimeout'://请求超时
                            // 重新上传;
                            return;
                    }
                    break;
                case 403: //授权无效,重新授权
                case 411: //缺少参数
                case 404: //Bucket/Object/Multipart Upload ID 不存在
                    // 重新授权;
                    // 继续上传;
                    return;
                case 500: //OSS内部发生错误
                    // 重新上传;
                    return;
                default:
                    break;
            }
        }
        //文件上传队列
        var upfiles = [];
     var upfiles1 = [];
        $(function () {
            //初始化文件上传队列
            $("#file").change(function (e) {
                var ufiles = $(this).prop('files');
                // console.log(ufiles[0])
                var upfiles1 = ufiles[0];
                var htm = "";
                for (var i = 0; i < ufiles.length; i++) {
                    htm += "<dl><dt>" + ufiles[i].name + "</dt><dd><div class=\"progress\"><div id=\"progress-bar_" + i + "\" class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"min-width: 2em;\">0%</div></div></dd></dl>";
                    upfiles.push({
                        num: i,
                        name: ufiles[i].name,
                        file: ufiles[i]
                    })
                }
                console.log('upfiles:', upfiles);
                applyTokenDo(uploadFile);
                $("#up_wrap").html(htm);
            });
            //上传
            $("#file-button").click(function () {
                applyTokenDo(uploadFile);
            });
            //续传
            $("#Continue-button").click(function () {
                applyTokenDo(reUploadFile);
            })
        })
    </script>
    
</body>

</html>

js


define(['jquery', 'bootstrap', 'backend', 'table', 'form','/assets/libs/layui/layui.js'], function ($, undefined, Backend, Table, Form,Layui) {

    var Controller = {
        index: function () {
            // 初始化表格参数配置
            layui.use('element', function(){
                var $ = layui.jquery
                ,element = layui.element; //Tab的切换功能,切换事件监听等,需要依赖element模块
                
                //触发事件
                var active = {
                  setPercent: function(){
                    //设置50%进度
                    element.progress('demo', '50%')
                  }
                  ,loading: function(othis){
                    var DISABLED = 'layui-btn-disabled';
                    if(othis.hasClass(DISABLED)) return;
                  
                    //模拟loading
                    var n = 0, timer = setInterval(function(){
                      n = n + Math.random()*10|0;  
                      if(n>100){
                        n = 100;
                        clearInterval(timer);
                        othis.removeClass(DISABLED);
                      }
                      element.progress('demo', n+'%');
                    }, 300+Math.random()*1000);
                    
                    othis.addClass(DISABLED);
                  }
                };
                
                $('.site-demo-active').on('click', function(){
                  var othis = $(this), type = $(this).data('type');
                  active[type] ? active[type].call(this, othis) : '';
                });
              });

        },
        
    };
    return Controller;
});




如果出现Roles may not be assumed by root accounts.报错则需要创建RAM用户


把创建好的AccessKey填到
protected $accessKeyId='xxxxx';
protected $accessKeySecret = 'xxxx';

配置好以后报You are not authorized to do this action. You should be authorized by RAM.的错误需要配置AliyunSTSAssumeRoleAccess 权限

还需要添加跨越


如果文件为私有访问权限,需要单独对访问的文件设置

  $config = config('oss');
             $bucket = $config['bucket']; //oss中的文件上传空间
             try {
                $ossClient = new OssClient($this->accessKeyId, $this->accessKeySecret,$this->endpointVideo);
            
                // 设置签名URL的有效期为 3600 秒 (1小时)
                $timeout = 3600;
                
                // 生成签名URL
                $signedUrl =$ossClient->signUrl($bucket,'uploads/20260313/1773389096488.mp4', $timeout);
                
                echo "签名URL: " . $signedUrl;
                
            } catch (OssException $e) {
                printf(__FUNCTION__ . ": FAILED\n");
                printf($e->getMessage() . "\n");
                return;
            }



© 著作权归作者所有,转载或内容合作请联系作者