多檔案斷點續傳,上傳視訊自動轉MP4和截圖,圖片格式轉換

剎影發表於2018-12-10

功能:自己寫的一個元件,根據呼叫傳過來的的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
            {
               
            }
        }
    }
}

 

相關文章