Ecstore/BBC 视频上传(一)

我们知道淘宝,京东商品都是有视频的,针对BBC产品改造实现视频上传功能,七牛适用。
一、前台视频上传 /data/www/product/app/topshop/view/item/edit.html
html部分:

<div class="form-group">
  <label for="" class="col-sm-2 control-label">上传视频:</label>
  <div class="col-sm-10">
    <div class="video-input">
      <{if $item.video_default_id}>
      <a class="select-image" data-toggle="modal" href="javascript:void;" data-target="#gallery_modal"><input type="hidden" name="video_default_id" value="<{$item.video_default_id}>"><div class="img-put"><video src="<{$item.video_default_id}>" width="100" height="100" controls="controls"><source src="<{$item.video_default_id}>" type=""></video></div></a>
      <{/if}>
    </div>
      <div class="multiple-upload pro-thumb video-upload" >
          <input type="file" class="video-file-input" name="video" data-size="10540000" data-ismodal="true" multiple="multiple" data-remote="<{url action=toputil_ctl_image@uploadVideos from=shop}>" accept="" data-type="item">
          <div class="btn btn-default text-blue act-gallery action-upload"><i class="glyphicon glyphicon-open"></i>上传视频</div>

      </div>
  </div>

</div>

js部分:

$('.video-upload').on('click', '.action-upload', function(e) {
      var file_input = $('.video-file-input')[0];
      var container = $('.video-file-input').parent();
      // var handle = container.find(options.handle);

      var type = file_input.getAttribute('data-type') ? file_input.getAttribute('data-type') : 'video';
      var imgCatId = $('.folder-info-item[data-open-state="1"]').attr('data-img-catid');

      var fileName = file_input.getAttribute('data-filename') ? file_input.getAttribute('data-filename') : 'upload_files';
      var size = file_input.getAttribute('data-size') ? file_input.getAttribute('data-size') : 10540000;
      size = Number(size) || options.size;


      var insertWhere = container.find(file_input.getAttribute('data-insertwhere') || '.image-box');

      var multiple = file_input.multiple;
      var isModal = file_input.getAttribute('data-ismodal');
      var url = file_input.getAttribute('data-remote')+'&type='+type+'&image_cat_id='+imgCatId;
      var inputName = file_input.getAttribute('name');
      var callback = file_input.getAttribute('data-callback');

      var data = new FormData();
      var files = file_input.files;

      if (!files || !Array.prototype.slice.call(files).every(function(file, i) {
          if (file.size > size) {
            $('#messagebox').message('上传视频 "' + file.name + '" 不能大于' + size / 1024 / 1024 + 'M!');

            return false;
          }
          if (multiple) {
            data.append(fileName + '[]', file);
          } else {
            data.append(fileName, file);
          }
          return true;
        })) return false;

      $.ajax({
        url: url,
        type: 'POST',
        data: data,
        cache: false,
        contentType: false,
        processData: false,
        success: function(rs) {
          try {
            rs = JSON.parse(rs);
          } catch (e) {}

          if (rs.success && rs.data) {
            if (callback) {
              return callback(rs);
            }
            var html = '';

            $.each(rs.data, function(k, data) {
              if (data.url) {
                html += '<a class="select-image" data-toggle="modal" href="javascript:void;" data-target="#gallery_modal"><input type="hidden" name="video_default_id" value="' + data.url + '"><div class="img-put"><video src="' + data.url + '" width="100" height="100" controls="controls"><source src="' + data.url + '" type="video/mov"></video></div></a>';
              }
            });
            $('.video-input').html(html);

          } else if (rs.message) {
            $('#messagebox').message(rs.message);
            return false;
          }
        },
        error: function() {
          $('#messagebox').message('上传出错,请重试');
        }
      });
    });

文件上传需ajax请求,form表单提交file值后台接受不到。。。

效果:
在这里插入图片描述

二、图片上传: /data/www/product/app/toputil/controller/image.php

添加uploadVideos方法,内容同uploadImages,需将
$objLibImage->rebuild($imageData['ident'], $imageType);
注释(打开也不报错,只会生成几个无用的文件)

三、视频配置项: /data/www/product/config/image.php

/**
     |--------------------------------------------------------------------------
     | 视频支持的格式
     | 暂时只支持 'avi', 'mov', 'rmvb', 'flv','mp4','flash','3gp'
     |--------------------------------------------------------------------------
     */
    'video_support_filetype' => ['avi', 'mov', 'rmvb', 'flv','mp4','flash','3gp'],
    //图片上传文件最大限制,如果上传大小超出PHP.ini配置,请修改PHP.ini
    'uploadedVideoMaxSize' => 1024*1024*10,// 10M

四、实现图片上传:新建 /data/www/product/app/image/lib/data/video.php

<?php

use Symfony\Component\HttpFoundation\File\UploadedFile;

class image_data_video {
    /**
     * 上传视频商家ID
     */
    public $sellerId = null;

    /**
     * 上传视频的店铺ID
     */
    public $shopId = null;

    /**
     * 上传视频的分类ID
     */
    public $imageCatId = null;


    public function __construct()
    {
        $this->objMdlImage = app::get('image')->model('images');
    }

    //上传视频支持的后缀
    public function getImageSupportFiletype()
    {
        return config::get('image.video_support_filetype');
    }

    private function __getImageParams( $file )
    {
        $imageParams = getimagesize($file);
        $data['width'] = $imageParams[0];
        $data['height'] = $imageParams[1];
        $data['type'] = $imageParams[2];
        return $data;
    }

    private function __checkImage( $fileObject )
    {
        $extension = $fileObject->getClientOriginalExtension();
        if( !in_array(strtolower($extension), $this->getImageSupportFiletype()) )
        {
            throw new \LogicException(app::get('image')->_('不支持该视频格式'));
        }

        //检查上传视频大小限制
        $this->__checkUploadedFileMaxSize($fileObject);

        $imageName = $fileObject->getClientOriginalName();
        if( strlen($imageName) > 200 )
        {
            throw new \LogicException(app::get('image')->_('视频文件名称过长,名称不能超过200个字符'));
        }
        return true;
    }

    private function __checkUploadedFileMaxSize($fileObject)
    {
        $phpIniMax = $fileObject->getMaxFilesize();
        $maxFilesize = config::get('image.uploadedVideoMaxSize');
        $maxFilesize = $maxFilesize > $phpIniMax ? $phpIniMax : $maxFilesize;

        if( $fileObject->getError() == UPLOAD_ERR_INI_SIZE  ||//上传文件大小限制
            $fileObject->getError() == UPLOAD_ERR_FORM_SIZE ||//POST上传大小表单限制
            $maxFilesize < $fileObject->getClientSize()
        )
        {
            throw new \LogicException(app::get('image')->_('超出限制,上传视频不能超过'.format_filesize($maxFilesize)));
        }
    }

    private function __preFileObject( $fileObject )
    {
        if(substr($fileObject,0,4) == 'http' )
        {
            $fileObject = $this->__getNetworkImage($fileObject);
        }
        elseif( !is_object($fileObject) )
        {
            if( file_exists($fileObject) )
            {
                $imageParams = pathinfo($fileObject);

                $file = tempnam(TMP_DIR,'tmpImage');
                kernel::single('base_filesystem')->copy($fileObject, $file);
                $size = filesize($file);

                $imageName = substr(strrchr($fileObject,'/'),1);
                $fileObject = new UploadedFile($file, $imageName, $imageParams['extension'], $size, 0, true);
            }
            else
            {
                $fileObject = new UploadedFile($fileObject['tmp_name'], $fileObject['name'], $fileObject['type'], $fileObject['size'], $fileObject['error']);
            }
        }

        return $fileObject;
    }

    /**
     * 商家:检查上传视频指定的视频类型和分类是否正确
     */
    public function setImageCatId($imageCatId, $imageType)
    {
        if( !$this->shopId  )
        {
            throw new \LogicException(app::get('image')->_('上传失败,店铺不存在'));
        }

        $filter = [
            'image_cat_id'=>$imageCatId,
            'img_type' => $imageType,
            'shop_id'=>$this->shopId,
        ];

        $objMdlImageCat = app::get('image')->model('image_cat');
        if(  !$objMdlImageCat->count($filter) )
        {
            throw new \LogicException(app::get('image')->_('上传指定的视频类型子分类不存在'));
        }

        $this->imageCatId = $imageCatId;
        return $this;
    }

    /**
     * 存储视频接口
     *
     * @param object $fileObject 继承SplFileInfo封装的类
     * @param string $from  上传视频用户类型
     */
    public function store( $fileObject, $from, $imageType, $test=false)
    {
        $fileObject = $this->__preFileObject( $fileObject );

        $this->__checkImage($fileObject);

        $file = $fileObject->getRealPath();
        $imageParams = $this->__getImageParams($file);
        $params['width'] = $imageParams['width'];
        $params['height'] = $imageParams['height'];
        $params['size'] = $fileObject->getClientSize();

        $params['image_name'] = htmlspecialchars(specialutils::filterInput($fileObject->getClientOriginalName()),ENT_QUOTES);
        if( empty($imageType) )
        {
            throw new \LogicException(app::get('image')->_('上传视频失败,上传视频类型不能为空'));
        }

        $params['image_cat_id'] = $this->imageCatId ? $this->imageCatId : 0;
        $params['img_type'] = $imageType;
        $params['last_modified'] = time();

        $storager = kernel::single('base_storager');
        $result = $storager->upload($fileObject);
        list($url,$ident,$storage) = explode('|', $result);

        $params['url'] = kernel::get_host_mirror_img().$url;
        $params['ident'] = $ident;
        $params['storage'] = $storage;

        $accountData = $this->__imageAttach($test);
        $params['target_id'] = $accountData['target_id'];
        $params['target_type'] = $accountData['target_type'];
        $params['disabled'] = 0;

        $params['file_type'] = $fileObject->getClientOriginalExtension();


        if( !in_array($imageType, config::get('image.image_type.'.$params['target_type'])) )
        {
            throw new \LogicException(app::get('image')->_('上传视频失败,上传视频类型错误'));
        }

        if( $row = $this->objMdlImage->getRow('id',['url'=>$params['url'],'target_id'=>$params['target_id'],['target_type'=>$params['target_type']]]) )
        {
            $this->objMdlImage->update($params, ['id'=>$row['id']]);
        }
        else
        {
            $this->objMdlImage->insert($params);
        }
        unlink($file);

        return $params;
    }

    /**
     * 设置上传视频的账号ID和类型
     *
     * @param string $from 上传视频用户类型
     * @param string $from 上传视频用户类型
     */
    public function setUploadImageAccount($from, $id)
    {
        $this->targetId = $id;

        $this->targetType = $from;

        if( !$this->targetId )
        {
            throw new \LogicException(app::get('image')->_('无上传视频权限'));
        }

        return $this;
    }

    public function setUploadShopId($shopId = null)
    {
        $this->shopId = $shopId;
    }

    /**
     * 视频ID,关联上用户类型ID
     *
     * @param string $from 上传视频用户类型
     */
    private function __imageAttach($test=false)
    {
        if( $this->targetId && $this->targetType )
        {
            if( $this->shopId )
            {
                $data['target_id'] = $this->shopId;
            }
            else
            {
                $data['target_id'] = $this->targetId;
            }

            $data['target_type'] = $this->targetType;
        }
        else
        {
            pamAccount::setAuthType('desktop');
            $data['target_id'] = pamAccount::getAccountId();
            $data['target_type'] = 'admin';
        }

        if( !$data['target_id'] && !$test )
        {
            throw new \LogicException(app::get('image')->_('无上传视频权限'));
        }

        return $data;
    }

    public function getImageTypeSize( $imageType )
    {
        if( empty($imageType) ) return false;

        $imageSetting = config::get('image.image_setting');

        $size = $imageSetting['normal']['size'];
        foreach( $imageSetting as $k=>$row )
        {
            if( $row['image_type'] && in_array($imageType, $row['image_type']) )
            {
                $size = $row['size'];
            }
        }

        if( !$size ) return false;
        $setImageSize = config::get('image.image_setting_set');
        if( in_array( $imageType, $setImageSize) )
        {
            $setSize = $this->getImageSetting($imageType);
        }

        if( !$setSize )
        {
            $setSize = config::get('image.image_default_set');
        }

        foreach( $size as $s )
        {
            $res[$s]['width'] = $setSize[$s]['width'];
            $res[$s]['height'] = $setSize[$s]['height'];
            $res[$s]['title'] = $setSize[$s]['title'];
        }

        return $res;
    }

    public function setImageSetting($imageType, $value)
    {
        return app::get('image')->setConf('image.set.'.$imageType, $value);
    }

    public function getImageSetting($imageType)
    {
        return app::get('image')->getConf('image.set.'.$imageType);
    }

    public function setImageDefault($url)
    {
        return app::get('image')->setConf('image.set.defaultPic', $url);
    }

    public function getImageDefault()
    {
        return app::get('image')->getConf('image.set.defaultPic');
    }

    /**
     * 商品视频相册视频生成
     *
     * @param $ident 需要生成相册视频唯一值
     * @param $sizes   生成视频大小
     *
     * @return bool
     */
    public function rebuild($ident, $imageType, $sizes = 0 )
    {
        if( !$sizes )
        {
            $sizes = $this->getImageTypeSize($imageType);
        }

        $storager = kernel::single('base_storager');
        $orgFile = $storager->getFile($ident);

        if( !file_exists($orgFile) || !$sizes ) return true;

        foreach($sizes as $s=>$value)
        {
            $tmpTarget = tempnam(TMP_DIR,'img');
            $w = $value['width'];
            $h = $value['height'];

            $orgFileSize = getimagesize($orgFile);
            if( $orgFileSize['0'] < $w )
            {
                $w = $orgFileSize['0'];
            }
            if( $orgFileSize['1'] < $h )
            {
                $h = $orgFileSize['1'];
            }

            image_clip::image_resize($orgFile, $tmpTarget, $w, $h);

            $imageParams = getimagesize($tmpTarget);
            $size = filesize($tmpTarget);
            $fileObject = new UploadedFile($tmpTarget, $images['image_name'], $imageParams['mime'], $size, 0, true);

            $storager->rebuild($fileObject, strtolower($s), $ident);
            unlink($tmpTarget);
        }

        return true;
    }

    /**
     * 存储网络视频
     *
     * @param string $imageUrl 视频URL地址
     */
    public function storeNetworkImage( $imageUrl, $from, $imageType, $test=false )
    {
        $fileObject = $this->__getNetworkImage($imageUrl);
        $imageId = $this->store($fileObject, $from, $imageType, $test);
        $file = $fileObject->getRealPath();
        unlink($file);
        return $imageId;
    }

    private function __getNetworkImage($imageUrl)
    {
        $imageContent = client::get($imageUrl)->getBody();
        $tmpTarget = tempnam(TMP_DIR, 'imageurl');
        file_put_contents($tmpTarget, $imageContent);

        $imageParams = getimagesize($tmpTarget);
        $size = filesize($tmpTarget);

        $imageName = substr(strrchr($imageUrl,'/'),1);

        if( $num = strpos($imageName,'?') )
        {
            $imageName = substr($imageName,0,$num);
        }

        $fileObject = new UploadedFile($tmpTarget, $imageName, $imageParams['mime'], $size, 0, true);
        return $fileObject;
    }
    /**
     * 存储服务器中移除视频源文件
     * @param array $ids 多个视频ID
     */
    public function removeImageFile($ids)
    {
        try{
            $data = $this->objMdlImage->getList('id,storage,ident,img_type',['id'=>$ids]);
            foreach( $data as $row )
            {
                $storager = kernel::single('base_storager',$row['storage']);

                $num = $this->objMdlImage->count(['ident'=>$row['ident']]);
                //七牛存储服务 同一个视频只生成一个唯一标示
                //如果不同店铺上传同一个视频,或导致一个唯一标示对应多条记录
                if( $num == 1 )
                {
                    $storager->remove($row['ident']);
                    $allsize = $this->getImageTypeSize($row['img_type']);
                    foreach($allsize as $s=>$value)
                    {
                        $storager->removeSizeFile($row['ident'],$s);
                    }
                }

                $delImageIds[] = $row['id'];
            }
        }
        catch( Exception $e)
        {
            if( $delImageIds )
            {
                $this->objMdlImage->delete(['id'=>$delImageIds]);
                throw new Exception('部分删除失败');
            }
            throw new Exception('删除失败');
        }
        $this->objMdlImage->delete(['id'=>$delImageIds]);

        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37826705/article/details/85234447
今日推荐