多文件断点续传,上传视频自动转MP4和截图,图片格式转换

功能:自己写的一个组件,根据调用传过来的的fileType判断是上传视频还是图片还是音频。可以选择多文件上传,同时也可以暂停,继续,取消,断网重连续传。如果上传的是视频,会自动转为mp4,自动截取一帧图片。如果上传的是.tif格式图片则转换为png格式(用的ffmpeg插件)。

界面:

前端代码:


@{
    ViewBag.Title = "Index";
    <link rel="stylesheet" href="/Content/gdsm/vendor/bootstrap-3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="/Content/gdsm/vendor/bootstrap-datepicker-1.6.4-dist/css/bootstrap-datepicker3.min.css">
    <link rel="stylesheet" href="/Content/gdsm/css/common.css">
    <link rel="stylesheet" href="/Content/gdsm/css/admin.css">
    <script src="/Content/gdsm/vendor/jquery-3.3.1/jquery-3.3.1.min.js"></script>
    <script src="/Content/gdsm/vendor/bootstrap-3.3.7/js/bootstrap.min.js"></script>
    <script src="/Content/gdsm/vendor/layer-v3.1.1/layer/layer.js"></script>
    <script src="/Content/gdsm/vendor/jquery.nicescroll-3.7.6/jquery.nicescroll.min.js"></script>
    <script type="text/javascript" src="~/Content/gdsm/vendor/bootstrap-datepicker-1.6.4-dist/js/bootstrap-datepicker.min.js"></script>
    <script type="text/javascript" src="~/Content/gdsm/vendor/bootstrap-datepicker-1.6.4-dist/locales/bootstrap-datepicker.zh-CN.min.js"></script>
    <script src="/Content/gdsm/js/common.js"></script>
    ViewData["datacategory"] = ViewContext.RouteData.Values["categoryData"];
    string fileType = ViewContext.RouteData.Values["categroy"].ToString();
}
    <div id="addShapeContent">
        <div class="panel">
            <div class="panel-heading">
                <h3 class="panel-title">文件上传</h3>
            </div>
            <div class="panel-body shape-upload p30">
                <div class="upload-box item">
                    @switch (fileType)
                    {
                        case "image":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".jpg,.jpeg,.png,.gif,.bmp,.tif">
                                选择文件
                            </div>
                            <p class="file-desc">(图片支持jpg, jpeg, png, gif, bmp, tif;大小不超过5M,推荐尺寸:4:3,16:9)</p>
                            break;
                        case "media":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".mp4,.flv,.avi,.wmv">
                                选择文件
                            </div>
                            <p class="file-desc">(视频支持mp4, flv, wmv, avi;大小不超过20M)</p>
                            break;
                        case "music":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".mp3">
                                选择文件
                            </div>
                            <p class="file-desc">(音频支持mp3大小不超过20M)</p>
                            break;
                        case "shape":
                            <div class="upload-btn">
                                <input type="file" name="uploadFile" multiple="multiple" accept=".jpg,.jpeg,.png,.gif,.bmp,.tif">
                                选择文件
                            </div>
                            <p class="file-desc">(图片支持jpg, jpeg, png, gif, bmp, tif;大小不超过5M,推荐尺寸:4:3,16:9)</p>
                            break;
                    }

                </div>
                <div class="item">
                    <div class="control-label">添加至</div>
                    <div class="control">
                        <select id="sltcategory" class="form-control">
                            @if (ViewData["datacategory"] != null)
                            {
                                foreach (var item in ViewData["datacategory"] as List<GDSMModel.JHResCategory>)
                                {
                                    <option value="@item.res_category_id">@item.res_category_name</option>
                                }
                            }
                        </select>
                    </div>
                </div>
                <div class="item">
                    <div id="prolabel" class="control-label" style="display:none">正在上传中</div>
                    <div class="control">
                        <ul id="proul" class="progress-lists mt34" style="height:135px; overflow-y:auto;"></ul>
                    </div>
                </div>
            </div>
            <div class="panel-footer">
                <button type="button" class="btn btn-lucency js-cancle pull-right ml20">关闭</button>
            </div>
        </div>
    </div>

    <div id="progressbar" style="display:none">
        <li class="progress-detail" id="****">
            <span class="name" title="####" style="height:30px;">####</span>
            <div class="progress progress-striped active">
                <div class="progress-bar progress-bar-success" role="progressbar"
                     aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"
                     style="width:0%;">
                </div>
            </div>
            <span class="num" style="width:30px;">0%</span>
            <label class="currIndex" style="display:none">0</label>
            <button class="btn btn-blue btn-sm" onclick="PauseAndContinue(this);" style="margin-right:10px">暂停</button>
            <button class="btn btn-blue btn-sm" onclick="Cancle(this);">取消</button>
        </li>
    </div>
    <script type="text/javascript">
        //用于存储file信息
        var filearr = new Array();
        //离线状态下的fileID
        var offlinefileids = new Array();
        $(function () {
            //数组加个删除功能
            Array.prototype.remove = function (val) {
                var index = this.indexOf(val);
                if (index > -1) {
                    this.splice(index, 1);
                }
            };

            //监听网络已连接事件
            window.addEventListener('online', Online);

            //上传功能
            $("input[type='file']").change(function () {
                var filelists = this.files;
                //切换下标签类型,防止上传同一文件OnChange触发不了
                $(this).attr("type", "text");
                $(this).attr("type", "file");
                for (var i = 0; i < filelists.length; i++) {
                    if (filelists == undefined) {
                        layer.open({
                            title: '错误提示'
                            , content: '您的浏览器暂不支持上传文件,建议使用IE9以上、FireFox、Chrome、360极速模式等浏览器。'
                        });
                        return;
                    }
                    if (filelists.length < 1) {
                        layer.open({
                            title: '错误提示'
                            , content: '请选择文件。'
                        });
                        return;
                    }

                    //验证格式类型
                    var fileSplit = filelists[i].name.toLowerCase().split(".");
                    var fileFormat = fileSplit[fileSplit.length - 1]; //获得文件结尾的类型如 zip rar 这种写法确保是最后的
                    if (validate(fileFormat, filelists[i].name)) {
                        $("#prolabel").show();
                        var fileid = uuid();//生成一个文件ID
                        var file = filelists[i];
                        var totalSize = filelists[i].size;//文件大小
                        var blockSize = 1024 * 1024;//块大小
                        var blockCount = Math.ceil(totalSize / blockSize);//总块数
                        //存储file信息
                        var data = new fileData(file, totalSize, blockCount, blockSize);
                        filearr[fileid] = data;
                        //存储执行上传中的文件id
                        offlinefileids.push(fileid);
                        //获取服务器上最近上传的文件块序号
                        //currIndex = 0;

                        //生成进度条
                        var progressbar = $("#progressbar").html();
                        //替换名称
                        progressbar = progressbar.replace(new RegExp("####", 'g'), file.name);
                        //替换ID
                        progressbar = progressbar.replace("****", fileid);
                        $("ul.progress-lists").append(progressbar);
                        //开始分块上传文件
                        UploadPost(fileid, file, totalSize, blockCount, blockSize);
                    }
                }
            });

        });

        //上传文件
        function UploadPost(fileid, file, totalSize, blockCount, blockSize) {
            var queryid = "#" + fileid;
            var state = $(queryid).find("button[style]").html();//获取暂停继续的状态
            var currIndex = parseInt($(queryid).find("label.currIndex").html());//获取文件块数
            var category = $("#sltcategory").val();
            if (!(state == "暂停")) {
                if ($(queryid).find("label.currIndex").html() == "-1") {
                    //取消上传,删除文件块
                    CancleAjax(queryid, fileid);
                }
                return; //暂停
            }
            try {

                var start = currIndex * blockSize;                  //文件流开始位置
                var end = Math.min(totalSize, start + blockSize);   //文件流结束位置
                var block = file.slice(start, end);                 //截取下来的文件流块信息

                //组装提交表单信息
                var formDataBlock = new FormData();
                formDataBlock.append('fileName', file.name);//文件名
                formDataBlock.append('blockCount', blockCount);//总块数
                formDataBlock.append('currIndex', currIndex);//当前上传的块下标
                formDataBlock.append('uploadId', fileid);//上传编号
                formDataBlock.append('fileType', "@fileType");//文件类别
                formDataBlock.append('categoryType', category)//分类
                formDataBlock.append('totalSize', totalSize)//文件大小,用于验证
                formDataBlock.append('data', block);

                //提交服务器
                $.ajax({
                    url: '/Admin/FileUpload/Upload',
                    type: 'post',
                    data: formDataBlock,
                    processData: false,
                    contentType: false,
                    success: function (res) {
                        block = null;
                        if ($(queryid).find("label.currIndex").html() == "-1") {
                            //取消上传,删除文件块
                            CancleAjax(queryid, fileid);
                        }
                        else if (res.Code === 1) {
                            //设置进度条
                            currIndex++;
                            var num = Math.round((currIndex) / blockCount * 100) + "%";
                            $(queryid).find("span.num").html(num);
                            $(queryid).find("div.progress-bar").css("width", num);
                            //如果当前文件块不是最后一个,递归上传其他文件块信息
                            if (currIndex < blockCount) {
                                $(queryid).find("label.currIndex").html(currIndex);
                                UploadPost(fileid, file, totalSize, blockCount, blockSize);
                            }
                            else {
                                //上传成功
                                $(queryid).fadeOut(2000, function () {
                                    $(this).remove();
                                    if ($("#proul").children().length <= 1)
                                        $("#prolabel").fadeOut("fast");
                                });
                                offlinefileids.remove(fileid);
                                filearr[fileid] = "";
                            }
                        }
                        else {
                            layer.open({
                                title: '错误提示'
                                , content: res.Msg
                            });
                        }
                    }, error: function (e) {
                        if (!navigator.onLine) {
                            layer.open({
                                title: '错误提示'
                                , content: '网络连接已断开。'
                            });
                        }
                        else if (e.status == 0) {
                            UploadPost(fileid, file, totalSize, blockCount, blockSize);
                        }
                        else {
                            layer.open({
                                title: '错误提示'
                                , content: e.responseText
                            });
                        }
                    }
                });
            } catch (e) {
                alert(e);
            }
        }
        //暂停
        function PauseAndContinue(obj) {
            var fileid = $(obj).parent().attr("id");
            if ($(obj).html() == "暂停") {
                $(obj).html("继续");
                offlinefileids.remove(fileid);
            }
            else {
                $(obj).html("暂停");
                var fdata = filearr[fileid];
                offlinefileids.push(fileid);
                UploadPost(fileid, fdata.file, fdata.totalSize, fdata.blockCount, fdata.blockSize);
            }
        }
        //取消
        function Cancle(obj) {
            $(obj).parent().find("label.currIndex").html("-1");
        }

        //取消上传,删除文件块
        function CancleAjax(queryid, fileid) {
            $.ajax({
                url: '/Admin/FileUpload/Cancle?id=' + fileid,
                datatype: "json",
                type: "GET",
                async: false,
                success: function () {
                    $(queryid).find("span.num").html("0%");
                    $(queryid).find("div.progress-bar").css("width", 0);
                    $(queryid).fadeOut(2000, function () {
                        $(this).remove();
                        if ($("#proul").children().length <= 1)
                            $("#prolabel").fadeOut("fast");
                    });
                }
            });
        }

        //网络连接上继续执行上传
        function Online() {
            for (var i = 0; i < offlinefileids.length; i++) {
                var fileid = offlinefileids[i];
                var fdata = filearr[fileid];
                UploadPost(fileid, fdata.file, fdata.totalSize, fdata.blockCount, fdata.blockSize);
            }
        }

        //验证
        function validate(fileType,filename)
        {
            var type = "@fileType";
            var result = true;
            switch (type) {
                case "image":
                    if (fileType != "jpg" && fileType != "jpeg" && fileType != "png" && fileType != "gif" && fileType != "bmp" && fileType != "tif" && fileType != "") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        }); 
                        result = false;
                    }
                    break;
                case "shape":
                    if (fileType != "jpg" && fileType != "jpeg" && fileType != "png" && fileType != "gif" && fileType != "bmp" && fileType != "tif" && fileType != "") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        });
                        result = false;
                    }
                    break;
                case "music":
                    if (fileType != "mp3") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        });
                        result = false;
                    }
                    break;
                case "media":
                    if (fileType != "mp4" && fileType != "flv" && fileType != "avi" && fileType != "wmv") {
                        layer.open({
                            title: '格式错误'
                            , content: filename + '的格式错误'
                        });
                        result = false;
                    }
                    break;
            }
            return result;
        }

        //生成GUID
        function uuid() {
            var s = [];
            var hexDigits = "0123456789abcdef";
            for (var i = 0; i < 36; i++) {
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
            }
            s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
            s[8] = s[13] = s[18] = s[23] = "-";

            var uuid = s.join("");
            //return uuid;
            return uuid.replace(new RegExp("-", 'g'), "");
        }

        //用于存储file信息
        function fileData(file, totalSize, blockCount, blockSize) {
            this.file = file;
            this.totalSize = totalSize;
            this.blockCount = blockCount;
            this.blockSize = blockSize;
        }
    </script>

后端代码:

using GDSMBLL;
using GDSMCommon;
using GDSMModel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace GDSMPlateForm.Areas.Admin.Controllers
{
    public class FileUploadController : Controller
    {
        public string oriVideoPathc = "";
        public string outVideoPathc = "";
        public string ffmpegPathc = System.Web.Hosting.HostingEnvironment.MapPath("~/Content/ffmpeg/ffmpeg.exe");

        // GET: Admin/FileUpload
        public ActionResult Index()
        {
            return View();
        }

        [Route]
        [HttpPost]
        public ActionResult Upload(string uploadId, int blockCount, int currIndex, string fileName,string fileType,string categoryType,int totalSize)
        {
            try
            {
                var file = Request.Files[0];
                //文件格式
                string format = Path.GetExtension(fileName);

                //路径
                MD5 md5 = new MD5CryptoServiceProvider();
                string cryptStr = "";

                #region 校验
                ValidateHelper vh = new ValidateHelper();
                if (file == null)
                    return Json(new UploadResult { Msg = "请选择文件" }, JsonRequestBehavior.AllowGet);
                if (blockCount < 1)
                    return Json(new UploadResult { Msg = "块数量不能小于1" }, JsonRequestBehavior.AllowGet);
                if (currIndex < 0)
                    return Json(new UploadResult { Msg = "块数量小于0" }, JsonRequestBehavior.AllowGet);
                if (string.IsNullOrWhiteSpace(uploadId))
                    return Json(new UploadResult { Msg = "上传编号为空" }, JsonRequestBehavior.AllowGet);
                if (!vh.IsValidateFileExtension(fileName))
                {
                    return Json(new UploadResult { Msg = "文件格式不支持" }, JsonRequestBehavior.AllowGet);
                }
                if (totalSize > vh.GetResTypeSize(fileType))
                {
                    return Json(new UploadResult { Msg = "文件超过指定大小" }, JsonRequestBehavior.AllowGet);
                }
                var result = new UploadResult { Code = 1, Msg = "上传成功~" };
                result.UploadID = uploadId;
                #endregion

                #region ==块处理==
                string relativePath = "/upload";
                if (!string.IsNullOrEmpty(fileType) && !string.IsNullOrEmpty(categoryType))
                {
                    relativePath = "/Content/resource/" + fileType + "/" + categoryType + "/" + uploadId;

                }
                string dir = System.Web.HttpContext.Current.Server.MapPath("~" + relativePath);
                if (Directory.Exists(dir) == false)
                {
                    Directory.CreateDirectory(dir);
                }

                //块文件名称
                var blockName = $"{uploadId}_{currIndex}.block";
                //块文件目录路径
                var blockPath = Path.Combine(dir, "block");
                //块文件目录对象
                DirectoryInfo blockDirectoryInfo = Directory.Exists(blockPath) ? new DirectoryInfo(blockPath) : Directory.CreateDirectory(blockPath);
                //块文件完整路径
                var blockFullPath = Path.Combine(blockPath, blockName);
                if (System.IO.File.Exists(blockFullPath))
                {
                    //块已上传,不做失败处理
                    return Json(new UploadResult { Code = 1, Msg = "该文件块已上传~" }, JsonRequestBehavior.AllowGet);
                }

                file.SaveAs(blockFullPath);

                #endregion


                #region ==块合并处理==
                //判断块文件是否已将上传完,上传完合并文件
                if (blockDirectoryInfo.GetFiles().Count().Equals(blockCount))
                {
                    //var timestamp = DateTime.Now.ToString("yyyMMdd");
                    string fileOldNmae = fileName;
                    fileName = uploadId + format;
                    //var filePath = Path.Combine(dir, timestamp);
                    var filePath = dir;
                    if (!Directory.Exists(filePath))
                    {
                        Directory.CreateDirectory(filePath);
                    }
                    //完整文件存储路径
                    var fileFullPath = Path.Combine(filePath, fileName);
                    //读取每个文件块写入文件流
                    using (var fs = new FileStream(fileFullPath, FileMode.Create))
                    {
                        for (var i = 0; i < blockCount; i++)
                        {
                            var path = Path.Combine(blockPath, $"{uploadId}_{i}.block");
                            var bytes = System.IO.File.ReadAllBytes(path);
                            fs.Write(bytes, 0, bytes.Length);
                        }
                        //删除所有文件块路径
                        Directory.Delete(blockPath, true);
                    }

                    #region md5加密
                    FileStream fileStream = new FileStream(fileFullPath, FileMode.Open);
                    //对面文件流进行md5加密
                    byte[] cryptBytes = md5.ComputeHash(fileStream);
                    //加密的二进制转为string类型
                    cryptStr = Convert.ToBase64String(cryptBytes);
                    fileStream.Close();
                    #endregion

                    result.FileInfo = new UploadFileInfo
                    {
                        FileName = fileName,
                        FilePath = fileFullPath
                    };

                    if (fileType == "media")
                    {
                        outVideoPathc = filePath + "\\" + uploadId + ".mp4";//转mp4格式路径
                        oriVideoPathc = fileFullPath;//原视频路径
                        string thubHeight = "150";
                        string frameIndex = "1";
                        string thubWidth = "200";
                        string thubImagePath = filePath + "\\" + uploadId + ".png";
                        FileConvertUtil.MediaExstractImage(ffmpegPathc, oriVideoPathc, thubHeight, frameIndex, thubWidth, thubImagePath);
                        format = ".mp4";
                        fileName = uploadId + format;

                        System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(ConvertMp4WithoutTxt));
                        thread.Start();

                    }
                    else if (fileType == "image" || fileType == "shape")
                    {
                        if (format == ".tif" || format == ".TIF")
                        {
                            format = ".png";
                            fileName = uploadId + format;
                            outVideoPathc = filePath + "\\" + uploadId + ".png";//转mp4格式路径
                            oriVideoPathc = fileFullPath;//原视频路径
                            System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(ConvertImageFormat));
                            thread.Start();
                        }
                    }


                    #region 信息存入数据库
                    JHResouce jhResouce = new JHResouce();
                    jhResouce.file_id = Guid.NewGuid().ToString();
                    jhResouce.file_name = fileName;
                    jhResouce.file_oldname = fileOldNmae;
                    jhResouce.file_path = Path.Combine(relativePath, fileName).Replace("\\", "/");
                    jhResouce.res_category_id = categoryType;
                    jhResouce.create_user_id = "";
                    jhResouce.create_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    jhResouce.md5 = cryptStr;
                    if (fileType == "media")
                    {
                        jhResouce.file_type = Path.Combine(relativePath, uploadId + ".png").Replace("\\", "/");
                    }
                    else
                    {
                        jhResouce.file_type = format;
                    }
                    HttpCookie cookieid = Request.Cookies["user_id"];
                    if (cookieid != null)
                    {
                        if (cookieid.Value != "")
                        {
                            jhResouce.create_user_id = cookieid.Value;
                        }
                    }
                    JHResouceBL hResouceBL = new JHResouceBL();
                    hResouceBL.Insert(jhResouce, GetTableName(fileType));
                    new JHLogBL().Insert(LogType.add, fileType + "添加操作,文件上传");
                    #endregion
                }

                #endregion

                return Json(result);


            }
            catch (Exception ex)
            {
                throw;
            }
        }

        /// <summary>
        /// 上传过程中取消上传,删除相应文件块
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public int Cancle(string id)
        {
            try
            {
                //获取文件块路径,删除文件块
                string dir = System.Web.HttpContext.Current.Server.MapPath("~/upload");
                var blockPath = Path.Combine(dir, id);
                Directory.Delete(blockPath, true);
                return 1;

            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 视频转换为mp4
        /// </summary>
        public void ConvertMp4WithoutTxt()
        {
            Process p = new Process();//建立外部调用线程
            p.StartInfo.FileName = ffmpegPathc; //System.Windows.Forms.Application.StartupPath + "\\ffmpeg.exe";//要调用外部程序的绝对路径
                                                // string StrArg = "-i concat:\"" + StrMP4A + "|" + StrMP4B + "\" -vcodec copy -acodec copy " + StrOutMp4Path + " -y";
                                                //string StrArg = "- i concat: \"" + StrMP4A + "|" + StrMP4B + "\" - vcodec copy - acodec copy "+ StrOutMp4Path + " -y";
                                                // string StrArg = "-i D:\\123.flv -i D:\\water.png -filter_complex \"overlay=10:10\" -b 1024k -acodec copy";
                                                // string StrArg = "-i "+StrMP4A+" -acodec copy -vcodec copy -f flv C:\\dis\\test1.mp4";
                                                // string StrArg =  "-i \"" + StrMP4A + "\" -qscale 6 \"" + StrOutMp4Path + "\"";// "-i " + StrMP4A + " -y  -vcodec h264 -b 1500 "+StrOutMp4Path ;
            string StrArg = "-i  " + oriVideoPathc + " -c:v libx264 -strict -2 " + outVideoPathc;
            p.StartInfo.Arguments = StrArg;

            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
            p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
            p.StartInfo.CreateNoWindow = true;//不创建进程窗口
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            p.Start();//启动线程
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();//关闭进程
            p.Dispose();//释放资源
            LogHelper.WriteLog("视频转换成功:" + outVideoPathc);
            LogHelper.WriteLog("开始删除原文件:" + oriVideoPathc);
            System.IO.File.Delete(oriVideoPathc);
            LogHelper.WriteLog("原文件删除成功");
        }

        /// <summary>
        /// 图片格式转换
        /// </summary>
        public void ConvertImageFormat()
        {
            Process p = new Process();//建立外部调用线程
            p.StartInfo.FileName = ffmpegPathc; //System.Windows.Forms.Application.StartupPath + "\\ffmpeg.exe";//要调用外部程序的绝对路径
                                                // string StrArg = "-i concat:\"" + StrMP4A + "|" + StrMP4B + "\" -vcodec copy -acodec copy " + StrOutMp4Path + " -y";
                                                //string StrArg = "- i concat: \"" + StrMP4A + "|" + StrMP4B + "\" - vcodec copy - acodec copy "+ StrOutMp4Path + " -y";
                                                // string StrArg = "-i D:\\123.flv -i D:\\water.png -filter_complex \"overlay=10:10\" -b 1024k -acodec copy";
                                                // string StrArg = "-i "+StrMP4A+" -acodec copy -vcodec copy -f flv C:\\dis\\test1.mp4";
                                                // string StrArg =  "-i \"" + StrMP4A + "\" -qscale 6 \"" + StrOutMp4Path + "\"";// "-i " + StrMP4A + " -y  -vcodec h264 -b 1500 "+StrOutMp4Path ;
            string StrArg = "-i  " + oriVideoPathc + " " + outVideoPathc;
            p.StartInfo.Arguments = StrArg;

            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
            p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
            p.StartInfo.CreateNoWindow = true;//不创建进程窗口
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            p.Start();//启动线程
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();//关闭进程
            p.Dispose();//释放资源
            LogHelper.WriteLog("图片转换成功:" + outVideoPathc);
            LogHelper.WriteLog("开始删除原文件:" + oriVideoPathc);
            System.IO.File.Delete(oriVideoPathc);
            LogHelper.WriteLog("原文件删除成功");
        }


        private void Output(object sendProcess, DataReceivedEventArgs output)
        {
            if (!String.IsNullOrEmpty(output.Data))
            {

            }
            else
            {
                //MessageBox.Show("视频合成失败");
            }
        }


        /// <summary>
        /// 根据类型获取表名
        /// </summary>
        /// <param name="stype"></param>
        /// <returns></returns>
        private string GetTableName(string stype)
        {
            string tableName = "";
            if (stype == "image")
            {
                tableName = "h_res_image";
            }
            else if (stype == "shape")
            {
                tableName = "h_res_shape";
            }
            else if (stype == "music")
            {
                tableName = "h_res_music";
            }
            else if (stype == "media")
            {
                tableName = "h_res_media";
            }
            return tableName;
        }

        /// <summary>
        /// 获取文件扩展名
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetExtension(string fileName)
        {
            if (string.IsNullOrWhiteSpace(fileName) || fileName.IndexOf(".") < 0)
            {
                return string.Empty;
            }
            var arr = fileName.Split('.');
            return arr[arr.Length - 1];
        }

        /// <summary>
        /// 根据类型验证上传文件类型
        /// </summary>
        /// <param name="stype"></param>
        /// <returns></returns>
        private bool IsValidateFileExtension(string fileExtension)
        {
            string format = System.Configuration.ConfigurationManager.AppSettings["format"].ToString();
            bool result = false;
            fileExtension = fileExtension.Replace(".", "");
            fileExtension = fileExtension.ToLower();
            if (format.Contains(fileExtension))
            {
                result = true;
            }
            return result;
        }
    }

    /// <summary>
    /// 文件上传结果
    /// </summary>
    public class UploadResult
    {
        /// <summary>
        /// 状态码 0失败 1成功
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// 消息
        /// </summary>
        public string Msg { get; set; }
        /// <summary>
        /// 上传编号,唯一
        /// </summary>
        public string UploadID { get; set; }
        /// <summary>
        /// 文件保存信息
        /// </summary>
        public UploadFileInfo FileInfo { get; set; }

    }

    public class UploadFileInfo
    {
        /// <summary>
        /// 文件保存名称
        /// </summary>
        public string FileName { get; set; }
        /// <summary>
        /// 文件保存路径
        /// </summary>
        public string FilePath { get; set; }
        /// <summary>
        /// 文件MD5值
        /// </summary>
        public string MD5 { get; set; }
    }

}

FileConvertUtil.cs(上传视频截图转格式功能)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace GDSMCommon
{
   public class FileConvertUtil
    {
        /// <summary>
        /// 获取视频的第一帧转换成图片
        /// </summary>
        /// <param name="ffmpegPath">ffmpeg路径</param>
        /// <param name="oriVideoPath">视频路径</param>
        /// <param name="thubHeight">转换后图片高度</param>
        /// <param name="frameIndex">第几帧</param>
        /// <param name="thubWidth">转换后图片的宽度</param>
        /// <param name="thubImagePath">转换后图片存储路径</param>
        public static void MediaExstractImage(string ffmpegPath,string oriVideoPath,string thubHeight,string frameIndex,string thubWidth,string thubImagePath)
        {
            Process p = new Process();//建立外部调用线程
            p.StartInfo.FileName =ffmpegPath;//要调用外部程序的绝对路径
            string command = string.Format("-i \"{1}\" -vframes 1 -r 1 -ac 1 -ab 2 -s {3}*{4} -f image2 \"{5}\"", ffmpegPath, oriVideoPath, frameIndex, thubWidth, thubHeight, thubImagePath);
            command = string.Format(" -i \"{0}\" -y -f image2 -ss 00:00:01 -t 0.000001 -s {1}*{2} \"{3}\"",oriVideoPath,thubWidth,thubHeight,thubImagePath);
            p.StartInfo.Arguments = command;
            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
            p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
            p.StartInfo.CreateNoWindow = true;//不创建进程窗口
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            p.Start();//启动线程
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();//关闭进程
            p.Dispose();//释放资源
            LogHelper.WriteLog("图片转换成功:"+ thubImagePath);
        }


        /// <summary>
        /// 视频转成相应格式
        /// </summary>
        /// <param name="ffmpegPath"></param>
        /// <param name="oriVideoPath"></param>
        /// <param name="outVideoPath"></param>
        public  static void ConvertMp4WithoutTxt(string ffmpegPath,string oriVideoPath, string outVideoPath)
        {
            Process p = new Process();//建立外部调用线程
            p.StartInfo.FileName = ffmpegPath;// System.Windows.Forms.Application.StartupPath + "\\ffmpeg.exe";//要调用外部程序的绝对路径
                                                                                                 // string StrArg = "-i concat:\"" + StrMP4A + "|" + StrMP4B + "\" -vcodec copy -acodec copy " + StrOutMp4Path + " -y";
                                                                                                 //string StrArg = "- i concat: \"" + StrMP4A + "|" + StrMP4B + "\" - vcodec copy - acodec copy "+ StrOutMp4Path + " -y";
                                                                                                 // string StrArg = "-i D:\\123.flv -i D:\\water.png -filter_complex \"overlay=10:10\" -b 1024k -acodec copy";
                                                                                                 // string StrArg = "-i "+StrMP4A+" -acodec copy -vcodec copy -f flv C:\\dis\\test1.mp4";
            string StrArg = "-i  " + oriVideoPath + " -c:v libx264 -strict -2 " + oriVideoPath; //"-i \"" + oriVideoPath + "\" -qscale 6 \"" + outVideoPath + "\"";// "-i " + StrMP4A + " -y  -vcodec h264 -b 500000 "+StrOutMp4Path ;

            p.StartInfo.Arguments = StrArg;

            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
            p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
            p.StartInfo.CreateNoWindow = true;//不创建进程窗口
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            p.Start();//启动线程
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();//关闭进程
            p.Dispose();//释放资源

        }

        /// <summary>
        /// 转换后调用方法
        /// </summary>
        /// <param name="sendProcess"></param>
        /// <param name="output"></param>
        private static void Output(object sendProcess, DataReceivedEventArgs output)
        {
            if (!String.IsNullOrEmpty(output.Data))
            {
                //处理方法...
                
            }
            else
            {
               
            }
        }
    }
}

 

posted @ 2018-12-10 17:37  漂移青春  阅读(322)  评论(0编辑  收藏  举报