前言
- 开通腾讯云点播。
- 后端脚本生成签名,本例用c#中的.ashx文件实现
- 前端上传,JQUERY+LAYUI的独立组件LAYER,进度条用的是HUI里的(原来的代码片段有,懒得改了)
- 访问权限问题一般在后端实现,此处不演示
开通腾讯云点播
官网地址:https://cloud.tencent.com/product/vod
后端签名生成
官方文档:https://cloud.tencent.com/document/product/266/9221
本例用c#中的.ashx文件实现
using System;
//加密
using System.Security.Cryptography;
using System.Text;
using System.Web;
//序列化
using System.Web.Script.Serialization;
namespace JOEYELUO.Web.Ashx
{
/// <summary>
/// TencentGetUploadSign 的摘要说明
/// </summary>
public class AppTencentUploadSign : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
//json序列化
var jsonSerializer = new JavaScriptSerializer();
context.Response.Write(jsonSerializer.Serialize(TencentGetUploadSign()));
}
public bool IsReusable
{
get
{
return false;
}
}
/// <summary>
/// 获取web端上传视频签名 https://cloud.tencent.com/document/product/266/9219
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
private Object TencentGetUploadSign()
{
try
{
//调用方法
var sign = new Signature
{
m_strSecId = "填自己的",
m_strSecKey = "填自己的",
m_qwNowTime = Signature.GetIntTimeStamp(),
m_iRandom = new Random().Next(0, 1000000),
m_iSignValidDuration = 3600 * 24 * 2,
//下面这个参数可以用来上传到子应用,API文档的参数介绍里有,子应用可用来隔离多用户,请换为你自己的子应用ID
m_vodSubAppId= 1500000000
};
//根据自己系统的规范返回,此处C#匿名类,序列化JSON后就是三个对象,状态、信息、签名,接口应该只需要签名,前两个可调试用
return new
{
Status = true,
Info = "获取签名成功",
signature = sign.GetUploadSignature()
};
}
catch (Exception ex)
{
return new
{
Status = false,
Info = "获取签名失败",
signature = ""
};
}
}
//官方文档的c#例子里的,增加了m_vodSubAppId
public class Signature
{
public string m_strSecId;
public string m_strSecKey;
public int m_iRandom;
public long m_qwNowTime;
public int m_iSignValidDuration;
//增加了m_vodSubAppId
public int m_vodSubAppId;
public static long GetIntTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Convert.ToInt64(ts.TotalSeconds);
}
private byte[] hash_hmac_byte(string signatureString, string secretKey)
{
var enc = Encoding.UTF8; HMACSHA1 hmac = new HMACSHA1(enc.GetBytes(secretKey));
hmac.Initialize();
byte[] buffer = enc.GetBytes(signatureString);
return hmac.ComputeHash(buffer);
}
public string GetUploadSignature()
{
string strContent = "";
strContent += ("secretId=" + Uri.EscapeDataString((m_strSecId)));
strContent += ("¤tTimeStamp=" + m_qwNowTime);
strContent += ("&expireTime=" + (m_qwNowTime + m_iSignValidDuration));
strContent += ("&random=" + m_iRandom);
//增加了m_vodSubAppId
strContent += ("&vodSubAppId=" + m_vodSubAppId);
byte[] bytesSign = hash_hmac_byte(strContent, m_strSecKey);
byte[] byteContent = System.Text.Encoding.Default.GetBytes(strContent);
byte[] nCon = new byte[bytesSign.Length + byteContent.Length];
bytesSign.CopyTo(nCon, 0);
byteContent.CopyTo(nCon, bytesSign.Length);
return Convert.ToBase64String(nCon);
}
}
}
}
前端样式及调用
官方文档:https://cloud.tencent.com/document/product/266/9239
例子中可能有hui前端的一些样式,这里就自行去引入吧。
这里的css部分用于:去除layer弹出的阴影,给hui进度条下面加上文字的百分比和停止上传按钮
CSS部分
<style>
.progressxia{
position:relative;
height:30px;
line-height:30px;
overflow:hidden;
width:400px;
}
.progressxia a{
text-decoration:none;
}
.progressNum{
position:absolute;
top:0;
left:0;
height:30px;
line-height:30px;
}
.progressCancel{
position:absolute;
top:0;
right:0;
height:30px;
line-height:30px;
}
body .myclass{
background:none;
box-shadow: none;
}
</style>
HTML部分
//此处有hui自带的文件上传样式,会隐藏原生file,但是会有两个input的值,js中可能需同时操作,不知道hui有没有一次操作的接口,没去研究
<span class="btn-upload form-group">
<input class="input-text upload-url" type="text" name="for-videoFile" id="for-videoFile" readonly><a href="javascript:void();" class="btn btn-default">浏览文件</a>
<input type="file" name="videoFile" id="videoFile" class="input-file">
</span>
<a href="javascript:void(0)" id="uploadstart" class="btn btn-primary"><i class="Hui-iconfont Hui-iconfont-upload"></i>确认上传</a>
<p class="mb-10"></p>
//下面是用来layer弹出进度条层的,初始隐藏,可自行block看下
<div style="display: none;" id="show">
<div class="progress radius">
<div class="progress-bar"><span class="sr-only" style="width: 0%"></span></div>
</div>
<div class="progressxia">
<div class="progressNum"><span>0</span>%</div>
<div class="progressCancel"><a href="javascript:void(0)" id="uploadcancel"><i class="Hui-iconfont Hui-iconfont-close"></i> 取消上传</a></div>
</div>
<div>
</div>
</div>
JS部分
//SDK 依赖 Promise,此处的前2个js
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.18.1/axios.min.js"></script>
//腾讯云点播核心
<script src="https://cdn-go.cn/cdn/vod-js-sdk-v6/latest/vod-js-sdk-v6.js"></script>
//其他的在母版文件里,我就没拷贝了。有JQUERY、HUI(他里面不知道是否打包了layui的独立layer组件,没有的话还要layui的layer.js)
<script>
$(function () {
function getSignature() {
//填你的签名生成地址
return axios.post("AppTencentUploadSign.ashx").then(function (response) {
return response.data.signature;
})
};
var tcVod = new TcVod.default({
getSignature: getSignature
});
//多个文件可以文件组
//var uploaderInfos = new Array();
$('#videoFile').on('change', function () {
//选择文件时的核验
validateUpload("videoFile");
});
//点上传按钮的操作
$('#uploadstart').on('click', function () {
var mediaFile = $("#videoFile")[0].files[0];
//先核验文件
if (!validateUpload("videoFile")) {
return;
}
//开始上传
var uploader = tcVod.upload({
mediaFile: mediaFile,
})
//用对象存储文件信息,我这里只需要把id和url拿到就好了,用不到
//var uploaderInfo = {
// videoInfo: uploader.videoInfo,
// isVideoUploadSuccess: false,
// isVideoUploadCancel: false,
// progress: 0,
// fileId: '',
// videoUrl: '',
// cancel: function () {
// uploaderInfo.isVideoUploadCancel = true;
// uploader.cancel()
// },
//}
//将单个文件信息对象存入数组
//uploaderInfos.push(uploaderInfo);
//上传开始,弹出进度条层
var show=layer.open({
type: 1,
title: false,
closeBtn: 0,
area: '400px',
shadeClose: false,
skin: 'myclass',
content: $("#show")
});
//进度条层中的取消按钮,这里取消后再传可以续传
$('#uploadcancel').on('click', function () {
if (typeof(uploader) != "undefined") {
uploader.cancel();
//关闭进度条层
layer.close(show);
}
});
//上传进度,自动轮询获得进度
uploader.on('media_progress', function (info) {
if (info.percent ==0) {
//没事干
}else if (info.percent < 1) {
$('#show .progressNum span').text(Math.floor(info.percent * 100));
$("#show .progress-bar span").css('width', Math.floor(info.percent * 100) + '%');
} else {
$('#show .progressNum span').text('0');
$("#show .progress-bar span").css('width', '0%');
layer.close(show);
}
})
//文件信息对象里的上传成功状态,这里我用不到
//uploader.on('media_upload', function (info) {
// uploaderInfo.isVideoUploadSuccess = true;
//})
// 回调结果说明
// type doneResult = {
// fileId: string,
// video: {
// url: string
// },
// cover: {
// url: string
// }
// }
uploader.done().then(function (doneResult) {
//这里可以在html里加input,通过$('#id').val();设置了
console.log("doneResult.fileId", doneResult.fileId);
console.log("doneResult.video.url", doneResult.video.url);
}).catch(function (err) {
layer.alert('上传失败,请确认腾讯云点播服务是否状态正常', { icon: 2 });
})
});
//限制上传文件的类型和大小
function validateUpload(objId) {
var flag = true;
var $obj = $('#' + objId);
var $forobj = $('#for-' + objId);
// 返回 KB,保留小数点后两位
var file = $obj[0].value;
if ($obj.val().length <= 0) {
layer.alert('请选择文件', { icon: 2 });
flag = false;
} else if (!/.(mp4)$/.test(file)) {
//我这只要mp4,多个文件类型可用|隔开
$obj.val('');
$forobj.val('');
layer.alert('仅支持.mp4格式', { icon: 2 });
flag = false;
} else if ((($obj[0].files[0].size).toFixed(2)) >= (100 * 1024 * 1024)) {
$obj.val('');
$forobj.val('');
layer.alert('请上传小于100M的视频', { icon: 2 });
flag = false;
}
return flag;
}
});
</script>
感想
官方用的vue,目前初步了解,还不是很熟,所以改了下。
做的时候找技术博发现有些是旧接口的,所以就写下这篇,自己以后也方便拷贝。