web实现大文件上传

445 阅读5分钟

1 前言

众所皆知,web上传大文件,是个难点。上传文件大小限制,页面响应时间超时,数据流分片长传,断点续传等,这些都是web开发中所可能遇到并且要解决的问题。

当然,有很多的小伙伴会说,度娘那里什么都有,哈哈,你说的对,但是我比较懒,比较图省事,用了第三方插件腾讯云

2 简介

不管是用的原声还是用的第三方插件,都要知道大文件分片上传的步骤

  1. 先对文件进行md5加密。使用md5加密的优点是:可以对文件进行唯一标识,同样可以为后台进行文件完整性校验进行比对。
  2. 拿到md5值以后,服务器端查询下该文件是否已经上传过,如果已经上传过的话,就不用重新再上传。
  3. 对大文件进行分片。比如一个100M的文件,我们一个分片是5M的话,那么这个文件可以分20次上传。
  4. 向后台请求接口,接口里的数据就是我们已经上传过的文件块。(注意:为什么要发这个请求?就是为了能续传,比如我们当一个文件传到一半的时候,突然想下班不想上传了,那么服务器就应该记住我之前上传过的文件块,当我打开电脑重新上传的时候,那么它应该跳过我之前已经上传的文件块。再上传后续的块)。
  5. 开始对未上传过的文件块进行上传。(这个是第二个请求,会把所有的分片合并,然后上传请求)。
  6. 上传成功后,服务器会进行文件合并。

3 引入腾讯云SDK

官方文档提供两种引入方式:script引入方式npm 引入方式

script 引入方式

下载 SDK 源码 到本地,然后按以下方式引入:

<script src="./vod-js-sdk-v6.js"></script>

使用 CDN 资源,可直接按以下方式引入:

<script src="https://cdn-go.cn/cdn/vod-js-sdk-v6/latest/vod-js-sdk-v6.js"></script>

npm 引入方式

// npm install vod-js-sdk-v6 之后,在页面中直接 import 引入
import TcVod from 'vod-js-sdk-v6'

代码实现

获取上传签名

调用后端的接口获取签名

function getSignature() {
    return axios.post(url).then(function (response) {
      return response.data.signature;
    })
};

当然也可以使用官方文档提供的Node.js 签名示例

var querystring = require("querystring");
var crypto = require('crypto');
// 确定 app 的云 API 密钥
var secret_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var secret_key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
// 确定签名的当前时间和失效时间
var current = parseInt((new Date()).getTime() / 1000)
var expired = current + 86400;  // 签名有效期:1天
// 向参数列表填入参数
var arg_list = {
secretId : secret_id,
currentTimeStamp : current,
expireTime : expired,
random : Math.round(Math.random() * Math.pow(2, 32))
}
// 计算签名
var orignal = querystring.stringify(arg_list);
var orignal_buffer = new Buffer(orignal, "utf8");
var hmac = crypto.createHmac("sha1", secret_key);
var hmac_buffer = hmac.update(orignal_buffer).digest();
var signature = Buffer.concat([hmac_buffer, orignal_buffer]).toString("base64");
console.log(signature);

secret_id和secret_key是需要注册腾讯云账号。

  • 鼠标定位右上角头像,点击访问管理
  • 在访问管理页面,点击访问秘钥,展开API秘钥管理
  • 新建秘钥,然后按照提示生成一条记录
  • 最后记录里会有secret_id和secret_key,添加到刚才的生成签名即可

image.png 有了签名之后就可以上传视频了,接下来关键来了。

上传视频

// 通过 import 引入的话,new TcVod(opts) 即可
// new TcVod.default(opts) 是 script 引入 的用法
const tcVod = new TcVod.default({
getSignature: getSignature // 前文中所述的获取上传签名的函数
})
const uploader = tcVod.upload({
mediaFile: mediaFile, // 媒体文件(视频或音频或图片),类型为 File
})
uploader.on('media_progress', function(info) {
console.log(info.percent) // 进度
})
// 回调结果说明
// type doneResult = {
//   fileId: string,
//   video: {
//     url: string
//   },
//   cover: {
//     url: string
//   }
// }
uploader.done().then(function (doneResult) {
// deal with doneResult
}).catch(function (err) {
// deal with error
})

还可以支持上传视频的同时上传封面

const uploader = tcVod.upload({
mediaFile: mediaFile,
coverFile: coverFile,
})
uploader.done().then(function (doneResult) {
// deal with doneResult
})

当然我上传错了也可以取消正在上传的文件或者视频

const uploader = tcVod.upload({
mediaFile: mediaFile,
coverFile: coverFile,
})
uploader.cancel()

SDK 支持自动断点续传功能,无需做额外操作。当上传意外终止时(如浏览器关闭、网络中断等),您再次上传该文件,可以从中断处继续上传,减少重复上传时间。

好了,现在就可以上传视频了,上传过程展示

上传展示.gif

上传成功了的话,想看有没有上传到腾讯云,找到云点播-音视频管理,就能看到你有没有 上传成功

音视频管理.png

这时候有同学就会问,播放视频呢?好,稍等,马上就来

###播放视频 播放也要引入官方的脚本,播放的脚本就不能npm的方式了,只能script和link引入js和css的方式了。

步骤1:在页面中引入文件

<link href="https://web.sdk.qcloud.com/player/tcplayer/release/v4.3.0/tcplayer.min.css" rel="stylesheet"/>
 <!--如果需要在 Chrome 和 Firefox 等现代浏览器中通过 H5 播放 HLS 格式的视频,需要在 tcplayer.vx.x.x.min.js 之前引入 hls.min.x.xx.xm.js。-->
 <script src="https://web.sdk.qcloud.com/player/tcplayer/release/v4.3.0/libs/hls.min.0.13.2m.js"></script>
 <!--播放器脚本文件-->
 <script src="https://web.sdk.qcloud.com/player/tcplayer/release/v4.3.0/tcplayer.v4.3.0.min.js"></script>

步骤2:放置播放器容器

<video id="player-container-id" width="414" height="270" preload="auto" playsinline webkit-playsinline>
</video>

步骤3:播放器初始化

在获取到的 fileID(媒资管理)中的视频 ID 与 appID(在账号信息>基本信息中查看)。 因为引入方式是script引入,我在index.html页面,把变量保存在了window

<script type="text/javascript">
  window._TCPlayer_ = TCPlayer;
</script>

通过fileID播放

var player = window._TCPlayer_ && window._TCPlayer_('player-container-id', { // player-container-id 为播放器容器 ID,必须与 html 中一致
    fileID: 'xxxxxxxxx', // 请传入需要播放的视频 fileID(必须)
    appID: 'xxxxxxxxx' // 请传入点播账号的 appID(必须)
    //私有加密播放需填写 psign, psign 即超级播放器签名,签名介绍和生成方式参见链接:https://cloud.tencent.com/document/product/266/42436
    //psign:'', // 参考 Key 防盗链说明
    //其他参数请在开发文档中查看
    plugins: {
      ContinuePlay: {
        // auto: true // 是否在播放时自动续播
      },
      ProgressMarker: true,
      ContextMenu: {
        statistic: true,
        levelSwitch: {
          open: true, // 打开切换提示
          // switchingText: '开始', // 开始切换时文案
          // switchedText: '成功', // 切换成功时文案
          // switchErrorText: '失败', // 切换失败时文案
        }
      }
    }
});

通过url播放

var player = window._TCPlayer_ && window._TCPlayer_('player-container-id', {}); // player-container-id 为播放器容器 ID,必须与 html 中一致
player.src(url); // url 播放地址

在实际项目中,因为腾讯云你不设置,会转好几种格式,产品说这样会浪费钱,然后自定义转换格式,添加防盗链,使用超级播放器。

切换播放

// 切换视频
player.loadVideoByID({
  fileID: 'xxxxxxxxx', // 请传入需要播放的视频 fileID(必须)
    appID: 'xxxxxxxxx' // 请传入点播账号的 appID(必须)
    //私有加密播放需填写 psign, psign 即超级播放器签名,签名介绍和生成方式参见链接:https://cloud.tencent.com/document/product/266/42436
    //psign:'', // 参考 Key 防盗链说明
});

最后

各位,早点下班,顺便留下你的脚印,谢谢

附上文档参考:上传播放