yii 上傳視頻(ajax)

實現一個功能:提交表單的時候,須要上傳視頻,把視頻上傳到oss上,而後把url做爲表單值傳到後端保存到數據庫。須要ajax異步實現。php

遇到了一個這樣報錯: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的配置被fpm/php.ini 覆蓋了. /etc/php/7.0/目錄下什麼狀況下會有fpm目錄, 什麼狀況下沒有fpm目錄, 有待研究啊. (盲猜是由於單獨安裝了php-fpm的緣由,待我有時間研究一下), 因此php -ini 顯示的php.ini 不必定就是程序使用的啊!!! (也是藉助了nginx的錯誤日誌, 發現緣由就是由於文件上傳大小沒有修改爲功)
相關文章
相關標籤/搜索