多文件断点续传,上传视频自动转MP4和截图,图片格式转换
2018-12-10 17:37
246 查看
功能:自己写的一个组件,根据调用传过来的的fileType判断是上传视频还是图片还是音频。可以选择多文件上传,同时也可以暂停,继续,取消,断网重连续传。如果上传的是视频,会自动转为mp4,自动截取一帧图片。如果上传的是.tif格式图片则转换为png格式(用的ffmpeg插件)。
界面:
前端代码:
[code] @{ 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[fil 1fff7 eid] = ""; } } 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>
后端代码:
[code]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(上传视频截图转格式功能)
[code]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 -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 { } } } }
阅读更多
相关文章推荐
- 视频上传过程中自动转换为flv格式并截图生成缩略图(Java调用命令实现)
- 视频上传过程中自动转换为flv格式并截图生成缩略图
- jQuery上传文件到服务器,实现量上传及压缩包导入,支持Office文档、PDF、图像、音视频和图纸等各类型文件。上传完成后系统自动为图片、音、视频类文件增加摘要及缩略图
- iOS大文件分片上传和断点续传 标签: iOS大文件分片断点续传获取视频获取图片 2016-05-17 15:52 4881人阅读 评论(8) 收藏 举报 分类: 技术—iOS 版权声明:本文为博
- 七牛上传视频文件 后截图功能
- 手机默认录制视频生成mp4文件,现在准备上传到服务器,网上有什么好的开源压缩框架吗?不压缩文件太大
- Asp.net MVC4 中的视频上传和视频截图,以及删除上传文件
- JSP上传视频后自动转成flv的核心JAVA方法
- PHP上传文件时自动分配路径的方法
- [Perl多线程]自动上传FTP文件的多线程扩展
- 实用小脚本 将写好的 sh 文件自动上传到 bin 目录
- 调用VLCjni.so播放rtsp视频流并录制成mp4文件
- 浏览器-点击预览视频文件(自动播放、循环播放)
- 上传文件、Validator自动校验数据、动态FormBean
- 使用FFMPEG从MP4封装中提取视频流到.264文件
- 上传文件时自动生成文件夹
- ffmpeg录制屏幕,生成MP4视频文件开发过程
- iOS上传视频道优酷视频文件MD5的获取等
- FTP自动上传文件脚本(客户端 DOS)
- 对上传的flv,mp4截图