实现一个功能:提交表单的时候,需要上传视频,把视频上传到oss上,然后把url作为表单值传到后端保存到数据库。需要ajax异步实现。

遇到了一个这样报错:Bad Request: 您提交的数据无法被验证。 这是因为form表单  里没有添加 ID属性,添加一个即可。

  1. 页面表单

    <form class="auto-form" method="post" id="art_form" action="<?= \Yii::$app->urlManager->createAbsoluteUrl(['mch/course/coursedir/add']);?>">
    <div class="form-group row">
    <div class="form-group-label col-sm-2 text-right">
    <label class="col-form-label required">上传完整视频</label>
    </div>
    <div class="col-sm-6">
    <input type="file" name="video" value=""/>
    <input type="text" name="video_url" value=""/>
    <img id="video" src="" alt="325×325" style="width:325px;height:325px;">
    </div>
    </div> //这是表单的一部分,要注意的是需要在<form id="art_form">code...</form>添加一个ID属性值,配合formData()
  2. ajax 发送数据(使用jquery)
    //上传视频, 这个url在yii里的写法是 index.php?r=moduleID/controllerID/actionID (写完整路径报错)
    url = 'index.php?r=mch/course/coursedir/upload-video';
    var video = $('input[name="video"]');var csrf = $('input[name="_csrf"]').val(); //csrf 不传也没有报错,好像是不传也可以(不知道会不会有安全隐患,表单里是传了csrf的)这里没用
    video.click(function () {
    video.change(function () {
    var obj = this;
    var formData = new FormData($('#art_form')[0]); //ajax 上传文件的时候,需要使用formData(),不要丢掉下标0
    $.ajax({
    type: 'post',
    url: url+'&fileName=video', //fileName 参数是后端处理文件需要使用的
    data: formData, // 数据
    //dataType: 'json',
    processData: false,
    contentType: false, //设置为false
    success: function (data) {
    if(data.status == 0){
    //success
    $('input[name="video_url"]').val(data.url);
    $('#video').attr('src', data.url);
    $(obj).off('change');
    }else{
    //fail
    }
    },
    error: function (err) { }
    })
    })
    })
  3. 服务器端处理文件并上传到oss里
    /**
    * 上传视频到oss,ajax返回视频url给页面
    * ajax传的fileName
    * 注意: 上传视频和上传图片不同, 需要修改php.ini文件里的upload_max_filesize 和 post_max_filesize 参数,默认好像只有几M ,肯定是不够的
    * 修改PHP上传文件大小限制的一个是nginx的client_max_body_size,还有一个是php.ini的限制。(包括upload_max_filesize, post_max_size, memory_limit)
    * $oldFile 参数是用来修改表单的时候,删除原来文件的一个标示, 如果传此参数, 则表示修改了上传文件, 需要删除原文件,在修改的表单的视图中先获取url然后通过ajax传一个oldFile参数
    * 上传视频MP4对应的mime类型是video/MP4 上传音频MP3 对应的类型是audio/MP3 上网查的是audio/mpeg 但是用这个就会报错上传文件类型不对,使用audio/MP3是对的
    * 上传的时候, 如果在network中看到报错 413 Request Entity Too Large , 因为 nginx 默认的上传限制较小,不支持大文件上传, 所以需要修改nginx的配置文件, 在nginx.conf或者对应项目的虚拟主机配置文件里加上 client_max_body_size = 40m;
    * 如果还小,还可以在=再设置大一点
    */
    public function actionUploadVideo($fileName, $oldFile='', $arr = ['video/mp4', 'audio/mp3'], $fileSize=10000000)
    {
    //判断文件是否合法
    $file = $_FILES[$fileName];
    if($file['error']>0){
    switch($file['error']){
    case 1:
    case 2:
    return '文件过大';
    case 3:
    return '上传文件不完整,请重新上传';
    case 4:
    return '请选择文件';
    case 6:
    return 'tmp不存在';
    case 7:
    return '没有权限';
    case 8:
    return '........';
    }
    }
    if(!in_array($file['type'], $arr)){
    return '上传文件类型不合法';
    }
    if($file['size']>$fileSize){
    return '上传文件过大';
    }
    $suffix = strrchr($file['name'], '.');
    $localdir = $file['tmp_name']; // 直接上传到oss 就不需要把文件从临时目录移动到服务器的目录里,直接从临时目录上传到oss 即可
    //引入ossSDK
    include \Yii::$app->basePath.'/extensions/aliyun-oss-php-sdk-2.2.4/autoload.php';
    //把视频上传到oss上
    try{
    $access_key = 'LTAI9c666666';
    $secret_key = 'f3zkCC666666';
    $domain = 'http://oss-cn-shenzhen.aliyuncs.com';
    $bucket = 'qa-xingzuo';
    $object = md5(time().uniqid()).$suffix; //文件名,要先获取上传的文件后缀
    $ossClient = new OssClient($access_key, $secret_key, $domain);
    $exist = $ossClient->doesObjectExist($bucket, $object); //判断oss上是否已经存在要上传的文件
    if($oldFile != ''){
    $oldObject = trim(strrchr($oldFile, '/'), '/');
    $ossClient->deleteObject($bucket, $oldObject); //删除原来的文件
    }
    //$ossClient->deleteObject($bucket, $object); exit;//删除文件
    if(!$exist){
    $ossClient->uploadFile($bucket, $object, $localdir);
    }
    //unlink($localdir); //删除本地文件, 后期可以优化一下
    $domain = explode('//', $domain);
    $url = 'http://'.$bucket.'.'.$domain[1].'/'.$object; //拼接访问路径,oss固定的访问格式
    $data = [
    'status' => 0,
    'msg' => 'success',
    'url' => $url,
    ];
    return $data;
    } catch(OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
    }
    }
  4. 特别说明:   今天把项目迁移到新服务器上之后, 突然发现ajax上传视频不能成功,  打印上传之后的$_FILE 数组为null  ,  找了半天原因,  主要排查以下几点: 
    1. 临时目录是不是没有读写权限,  特意改了一下upload_tmp_dir  并给了777 权限,  还是不行, 证明不是这个原因, 而且在旧服务器上, 根本没有设置upload_tmp_dir. 是注释掉的.
    2. 是不是upload_max_filesize和post_max_size设置的大小太小, 改成40m 还是不行(这个php.ini是通过php -ini命令显示的路径找的,  /etc/php/7.0/cli/php.ini)    修改40m 还是不行 ,包括memory_limit 都看了没问题, nginx的client_max_body_size 设置的是100m  没问题
    3. 甚至看了网上说nginx转发的URL必须设置proxy_set_header才能使用ajax上传数据, 于是改
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      # 增加了这三行, 但----还是不行 (又被我删除了) 实际上只有proxy_pass 转发就OK了(ps: 迁移服务器是吧原来的域名nginx转发了, 目的是避免前端修改接口)
    4. 还有网上看到在linux环境下,php5.3.3以前php-fpm还没有被php收录,配置php基本都在php.ini里面,php5.3.3及以后,除了在php.ini配置以外,还可以在php-fpm.conf里面配置,而php-fpm.conf优先级比php.ini高。但是php-fpm.conf里并没有发现配置文件上传的相关参数, 不过 突然想到fpm目录下的php.ini文件, 尝试修改了这个文件, 发现 成功了.  旧服务器上没有fpm目录, 新服务器上的php-fpm是单独安装的, 所以可能是这个原因导致多了一个fpm目录, 然后 cli/php.ini的配置是针对命令行访问PHP项目的,fpm/php.ini是针对浏览器访问PHP项目的. /etc/php/7.0/目录下什么情况下会有fpm目录, 什么情况下没有fpm目录, 有待研究啊. (盲猜是因为单独安装了php-fpm的原因,待我有时间研究一下), 所以php -ini 显示的php.ini 不一定就是程序使用的啊!!! (也是借助了nginx的错误日志, 发现原因就是因为文件上传大小没有修改成功)

yii 上传视频(ajax)的更多相关文章

  1. ajax 异步上传视频带进度条并提取缩略图

    最近在做一个集富媒体功能于一身的项目.需要上传视频.这里我希望做成异步上传,并且有进度条,响应有状态码,视频连接,缩略图. 服务端响应 { "thumbnail": "/ ...

  2. mvc实现上传视频预览

    上个项目中用到了上传视频,本来打算用百度的webuploader做的,但是webuploader可能有个毛病就是不能上传太大的东西. 于是乎,只能换个方法做了啊,看了半天最终决定用传统的uploade ...

  3. 动态获取爱奇艺上传视频mp4格式url地址

    有时候,在工作中有些客户需要用到视频,我们大家都知道视频是非常的耗费流量的,因此,如果因为项目要求客户单独买台视频服务器是非常划不来的.那么将视频上传到优酷,爱奇艺等视频网站来托管那是一件很好的解决方 ...

  4. CKEditor上传视频(java)

    CKEditor上传视频 CKEditor批量上传图片flvplayer.swf播放器CKEditor整合包(v4.6.1) ------------------------------------ ...

  5. plupload分片上传视频文件源码展示

    plupload分片上传视频文件目录结构如下: |- images//视频上传小图片 |-js// plupload js文件 |-uploads//视频文件存放文件夹 里面是按日期存放 |-ajax ...

  6. plupload上传视频插件jQuery+php

    我在网上找到一个很好的视频上传插件,经过我的一些整理.补充,在这里分享给大家. 这个视频插件是新浪微博plupload上传视频插件,支持格式有mpg,m4v,mp4,flv,3gp,mov,avi,r ...

  7. PHP后台代码 及 iOS客户端--AF实现上传视频

    //视频转换为MP4 //转码操作... _hud.mode = MBProgressHUDModeIndeterminate; _hud.labelText = @"转码中..." ...

  8. Android-调用优酷SDK上传视频

    最近在研究用优酷的SDK来进行视频上传的功能,由于优酷的SDK只是提供了一个上传的sample code,没有涉及到授权的过程,对于新手来说,可能非常棘手,现在分享一下我的思路:   程序实现前我们先 ...

  9. ASP.NET播客(留言时间,投票IP,留言限字数,上传视频)

    留言发布时间功能: 界面: 前台代码: 在Datalist控件中: 在<%#getIsDate(Convert.ToString(Eval("issuanceDate"))) ...

随机推荐

  1. Java中关于Integer, String 类型变量 == 与 equals 判断的坑

    == 与 equals()的联系: ==: 我们都知道Java中 == 对用于基础数据类型(byte, short, int, long, float, double, boolean, char)判 ...

  2. STL string 常见用法详解

    string 常见用法详解 1. string 的定义 //定义string的方式跟基本数据类型相同,只需要在string后跟上变量名即可 string str; //如果要初始化,可以直接给stri ...

  3. Linux就该这么学——初识vim编辑器

    在Linux系统中一切都是文件,而配置一个服务就是在修改其配置文件的参数 初识Vim编辑器 Vim编辑器顾名思义就是用来编写脚本程序的”记事本” Vim编辑器模式 : 命令模式 : 控制光标移动,可对 ...

  4. php栈的定义和出栈、入栈的实现

    栈是线性表的一种,他的特点是后入先出,可以这么理解,栈就像一个存东西的盒子,先放进去的在最底层,后放进去的在上层,因为上层的东西把底层的东西压住了,下层的想要出去就必须把上层的先拿开才行. 定义:栈是 ...

  5. 百度音乐接口api

    百度音乐接口   百度音乐全接口 http://tingapi.ting.baidu.com/v1/restserver/ting 请求方式:GET 参数处理:format=json&calb ...

  6. INPUT和CONSTRUCT指令——范例报表查询,作用让用户输入数据,自动生成SQL的WHERE条件,带开窗查询

    INPUT指令 说明:1. 当程序执行到INPUT指令时,会将控制权交给用户,让用户输入数据.2. 用户输入完字段的数据,会将数据回传给程序中的变量接收.3. 只要执行到INPUT的指令,程序会将每个 ...

  7. centos7 源码安装 MongoDb

    1.下载源码包 curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.2.12.tgz 2.解压 放到 /usr/local/ ...

  8. redis的keys常用操作及redis的特性

    redis的keys常用操作 1.获得所有的keys: keys * 2.可以模糊查询 keys:keys  my* 3.删除keys:del mymkey1 mykey2 4.是否存在keys:ex ...

  9. java写webservice接口

    有一个需求:要求根据设备mac和终端设备类型来查询设备库存状态. 接口协议是采用webservice协议,信息交互方式为xml格式信息 输入参数存放到XML各个节点下,并转为一个String,作为接口 ...

  10. python 访问权限

    访问权限 权限: 公有的:类中的普通属性和方法,默认都是公有的,可以在类的内部.外部.子类中使用 私有的:定义是在前面加两个'_',只能在本类的内部使用,不能再外部及子类中使用 示例: class P ...