这篇文章主要针对.net core 加 layui进行分片上传视频,希望可以帮助到各大网友
话不多说,直接上代码
前端代码
@{
ViewData["Title"] = "上传视频界面";
Layout = "~/Views/Shared/_MyLayout.cshtml";
}
<style type="text/css">
.mask {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #000;
opacity: 0.8;
filter: alpha(Opacity=80);
-moz-opacity: 0.8;
z-index: 999;
display: none;
}
.loading {
position: fixed;
width: 300px;
left: 50%;
margin-left: -150px;
top: 200px;
height: 18px;
border-radius: 10px;
background: #fff;
z-index: 9999;
overflow: hidden;
display: none;
}
</style>
<body>
<div class="layui-main">
<input type="hidden" name="form_submit" value="ok" />
<div class="layui-form-item">
<label class="layui-form-label">视频:</label>
<input type="hidden" id="totalPage" value="0" />
<input type="hidden" id="page" value="1" />
<input type="hidden" id="status" value="0" />
<div class="layui-input-block">
<button type="button" class="layui-btn" id="fileUpload"><i class="layui-icon"></i>上传文件</button>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">视频名:</label>
<div class="layui-input-block">
<input type="text" name="name" id="name" value="" lay-verify="title" autocomplete="off" readonly="true"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" id="test9">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</div>
<div class="mask"></div>
<div class="loading">
<div class="layui-progress layui-progress-big" lay-showpercent="true" lay-filter="uploadProgress">
<div class="layui-progress-bar layui-bg-red" lay-percent="0%"></div>
</div>
</div>
<!-- 注意:如果你直接复制所有代码到本地,上述js路径需要改成你本地的 -->
<script>
layui.use(['upload', 'element', 'layer'], function () {
// var form = layui.form;
//var upload = layui.upload;
//var element = layui.element;
//var $ = layui.$;
var $ = layui.jquery
, upload = layui.upload
, element = layui.element
, layer = layui.layer;
upload.render({
elem: '#fileUpload',
url: '/Video/UploadFiles', //处理上传文件接口
accept: 'file',
bindAction: '#test9',
auto: false,
// acceptMime: '*.*',//允许上传的文件类型
before: function (obj) {
element.progress('uploadProgress', '0%');//进度条清0
$('.mask').show();//遮罩层
$('.loading').show();//显示进度条
var data = this.data;
var files = obj.pushFile();//选择的文件推入obj
var LENGTH = 500 * 1024; //每片文件大小
obj.preview(function (index, file, result) {
var totalSize = file.size;//文件总大小
var totalPage = Math.ceil(totalSize / LENGTH);//总共上传的片数
$('#totalPage').val(totalPage);
$('#page').val('1');
$('#status').val('1');
var fileName = file.name;//获取文件名
$('#name').val(fileName);
var fileExt = fileName.substr(fileName.lastIndexOf('.') + 1);//获取文件后缀
fileName = fileName.substr(0, fileName.lastIndexOf('.'));//获取不带后缀的文件名
var progressTimer = setInterval(function () {
var totalPage = parseInt($('#totalPage').val());
var page = parseInt($('#page').val());
var status = $('#status').val();
if (parseInt(totalPage) == parseInt(page) && (parseInt(status) == 2 || parseInt(status) == -1)) {
clearInterval(progressTimer);//上传成功或失败停止上传
} else {
//状态为1的时候上传
if (status == 1) {
$('#status').val('0');
data.data = file.slice((page - 1) * LENGTH, page * LENGTH);
data.lastModified = file.lastModified;
data.fileName = fileName;
data.page = page;
data.totalPage = totalPage;
data.fileExt = fileExt;
// data.index = index;
var r = ''
for (var i = 1; i < 11; i++) {
r += Math.round(Math.random() * 20)
}
data.SName = r;
if (page >= totalPage - 1) {
}
obj.upload(index, file.slice((page - 1) * LENGTH, page * LENGTH));//从文件中截取进行分片上传
}
}
}, 100);
});
},
done: function (res) {
if (res.status == 1) { //分片上传
var page = parseInt($('#page').val());
var totalPage = parseInt($('#totalPage').val());
element.progress('uploadProgress', Math.ceil(page * 100 / totalPage) + '%');//更新进度条
page = page + 1;//上传下一片
console.log(page);
$('#page').val(page);
$('#status').val('1');
} else if (res.status == 2) { //上传完成
element.progress('uploadProgress', '100%');
$('#status').val('2');
$('#downUrl').val(res.downUrl);
layer.msg('上传成功', { time: 1000, anim: 0 }, function () {
$('.mask').hide();//隐藏遮罩层
$('.loading').hide();//隐藏进度条
});
} else { //上传错误
$('#status').val('-1');
element.progress('uploadProgress', '0%');
console.log(!typeof (res.downUrl) == "undefined");
if (typeof (res.downUrl) == "undefined") {
} else {
$('#downUrl').val(res.downUrl);
}
layer.msg("上传失败,请重试", { time: 3000, anim: 0 }, function () {
$('.mask').hide();
$('.loading').hide();
});
}
},
error: function () {
$('.mask').hide();
$('.loading').hide();
}
});
});
</script>
</body>
后台代码,如需进行m3u8格式转换需要自行下载ffmpeg.exe,下载之后直接丢入项目根目录就行
/// <summary>
/// 上传分片文件
/// </summary>
/// <param name="collection"></param>
/// <returns></returns>
public async Task<object> UploadFiles([FromForm] IFormCollection collection)
{
FormFileCollection filelist = (FormFileCollection)collection.Files;
var data = filelist["data"];
string lastModified = Request.Form["lastModified"].ToString();
var total = Request.Form["totalPage"];
var fileName = Request.Form["fileName"];
var index = Request.Form["page"];
var Vname = Request.Form["SName"];
var fileExt ="."+ Request.Form["fileExt"];
//$"{Directory.GetCurrentDirectory()}/wwwroot/"
string temporary = Path.Combine($"{Directory.GetCurrentDirectory()}/wwwroot/", lastModified);//临时保存分块的目录
try
{
if (!Directory.Exists(temporary))
Directory.CreateDirectory(temporary);
string filePath = Path.Combine(temporary, index.ToString());
if (!Convert.IsDBNull(data))
{
await Task.Run(() => {
FileStream fs = new FileStream(filePath, FileMode.Create);
data.CopyTo(fs);
fs.Close();
});
}
object mergeOk = false;
//string Time = DateTime.Now.ToString("yyMMddHHmmss");
string Time = Vname;
Dictionary<string, object> result = new Dictionary<string, object>();
if (total == index)
{
mergeOk = await FileMerge(lastModified, fileExt, Time);
result.Add("number", index);
result.Add("mergeOk", mergeOk);
result.Add("VideoId", Time);
result.Add("status", 2);
}
else
{
result.Add("number", index);
result.Add("mergeOk", mergeOk);
result.Add("VideoId", Time);
result.Add("status", 1);
}
if ((bool)mergeOk)
{
// string fileExt = Path.GetExtension(fileName);//获取文件后缀
DirectoryInfo di = new DirectoryInfo($"{Directory.GetCurrentDirectory()}/wwwroot/" + Time + "/");
if (!di.Exists)
{
di.Create();
}
di = new DirectoryInfo(@"C:\Users\Administrator\Desktop\dist\media\" + Time + @"\");
if (!di.Exists)
{
di.Create();
}
//$"{Directory.GetCurrentDirectory()}/wwwroot/" + Time + "/"
Convert2Flv($"{Directory.GetCurrentDirectory()}/wwwroot/" + Time + "/" + Time + "" + fileExt, @"C:\Users\Administrator\Desktop\dist\media\" + Time + @"\");
System.IO.File.Delete($"{Directory.GetCurrentDirectory()}/wwwroot/" + Time + "/" + Time + "" + fileExt);//删除文件
Directory.Delete($"{Directory.GetCurrentDirectory()}/wwwroot/" + Time);//删除文件夹
}
return result;
}
catch (Exception ex)
{
Directory.Delete(temporary);//删除文件夹
throw ex;
}
}
/// <summary>
/// 分片文件进行合并
/// </summary>
/// <param name="lastModified"></param>
/// <param name="fileExts"></param>
/// <param name="NewfileName"></param>
/// <returns></returns>
public async Task<object> FileMerge(string lastModified, string fileExts, string NewfileName)
{
string erro = "";
bool ok = false;
try
{
var temporary = Path.Combine($"{Directory.GetCurrentDirectory()}/wwwroot/", lastModified);//临时文件夹
//fileName = Request.Form["fileName"];//文件名
string fileExt = fileExts;//获取文件后缀
var files = Directory.GetFiles(temporary);//获得下面的所有文件
DirectoryInfo di = new DirectoryInfo($"{Directory.GetCurrentDirectory()}/wwwroot/" + NewfileName + "/");
if (!di.Exists)
{
di.Create();
}
var finalPath = Path.Combine($"{Directory.GetCurrentDirectory()}/wwwroot/" + NewfileName + "/", NewfileName + fileExt);//最终的文件名(demo中保存的是它上传时候的文件名,实际操作肯定不能这样)
var fs = new FileStream(finalPath, FileMode.Create);
foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))//排一下序,保证从0-N Write
{
var bytes = System.IO.File.ReadAllBytes(part);
await fs.WriteAsync(bytes, 0, bytes.Length);
bytes = null;
System.IO.File.Delete(part);//删除分块
}
fs.Close();
Directory.Delete(temporary);//删除文件夹
ok = true;
}
catch (Exception ex)
{
erro = ex.Message;
}
return ok;
}
/// <summary>
/// 转成m3u8格式
/// </summary>
/// <param name="vFileName"></param>
/// <param name="ExportName"></param>
/// <returns></returns>
public bool Convert2Flv(string vFileName, string ExportName)
{
try
{
//vFileName = @"C:\file\202203241822557127010848733.mp4";
//ExportName = @"C:\file\111\";
string Command = @" -i " + vFileName + " -profile:v baseline -level 3.0 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls " + ExportName + "ylky.m3u8"; //m3u8格式
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = @"ffmpeg.exe";
p.StartInfo.Arguments = Command;
p.StartInfo.WorkingDirectory = $"{Environment.CurrentDirectory}";
#region cmd执行
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
p.Start();//启动线程
p.WaitForExit();//等待完成
p.Close();//关闭进程
p.Dispose();//释放资源
convertVideoImage(vFileName, ExportName);
#endregion
}
catch (System.Exception e)
{
throw e;
}
return true;
}
/// <summary>
/// 截取视频图片作为封面
/// </summary>
/// <param name="VideoPath"></param>
/// <param name="savaRd"></param>
/// <returns></returns>
public string convertVideoImage(string VideoPath = "", string savaRd = "")
{
string str_MyProg = $"{Environment.CurrentDirectory}";
if (string.IsNullOrEmpty(VideoPath))
{
return string.Empty;
}
string str_CommandArgs = "";
var file1 = new FileInfo(VideoPath);
if (file1.Exists)
{
try
{
//string save_folder = file1.FullName.Replace(file1.Name, "");
string image_file = file1.Name.Replace(file1.Extension, ".jpg");
string save_folder = savaRd;
//#设置参数以直接输出图像序列(帧),第3秒
str_CommandArgs = "-i " + VideoPath + " -ss 00:00:03 -vframes 1 -an -y -f mjpeg " + save_folder + image_file;
System.Diagnostics.ProcessStartInfo cmd_StartInfo = new System.Diagnostics.ProcessStartInfo();
cmd_StartInfo.FileName = @"ffmpeg.exe";
cmd_StartInfo.Arguments = str_CommandArgs;
cmd_StartInfo.WorkingDirectory = $"{Environment.CurrentDirectory}";
cmd_StartInfo.RedirectStandardError = false; //set false
cmd_StartInfo.RedirectStandardOutput = false; //set false
cmd_StartInfo.UseShellExecute = true; //set true
cmd_StartInfo.CreateNoWindow = true; //don't need the black window
//创建一个进程,分配它的ProcessStartInfo并启动它
System.Diagnostics.Process cmd = new System.Diagnostics.Process();
cmd.StartInfo = cmd_StartInfo;
cmd.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
cmd.Start();
//System.Threading.Thread.Sleep(1000);
cmd.WaitForExit();//等待完成
cmd.Close();
cmd.Dispose();
return image_file;
}
catch (Exception ee)
{
throw new Exception(ee.StackTrace + ee.Message + " for: " + str_MyProg + " " + str_CommandArgs);
}
}
else
{
throw new Exception("No exists file:" + VideoPath);
}
}
个人理解,不对的大家可以相互交流。不喜勿喷,谢谢。