【前端】jszip+file-saver:多个视频url下载到zip、页面预加载视频、预览视频、强制刷新视频

文章目录

场景

服务端下发视频链接,前端可以多选,下载到一个zip中。

代码

需要用到的库:

javascript 复制代码
import { saveAs } from "file-saver";
import JSZip from "jszip";

将视频链接url转成Blob

javascript 复制代码
const handleGetBlob = async (url) => {
	if (!url.length) return;
	const blob = await (await fetch(url)).blob();
	return blob;
};

Blob简介:

Blob 是一种用来存储大块二进制数据(比如文件、图片、视频等) 的对象。你可以把它想象成一个"包裹",里面装着各种类型的数据,比如文本、图片、视频等等。

比如,当你上传一张图片到网页时,浏览器会把它暂时存放在内存 中,而不是直接发送到服务器。这时候,这张图片就会被封装成一个 Blob 对象。你也可以用 Blob 来存储一些临时的数据,比如生成一个文件或者处理视频流。

在前端开发中,Blob 很常用,比如:

  • 处理文件上传:当你上传文件时,文件会被转换成 Blob,方便在浏览器中预览或处理。
  • 缓存数据:你可以把一些数据(比如下载的内容)存放在 Blob 中,避免频繁请求服务器。
  • 生成下载链接:通过 Blob,你可以动态生成一个文件,让用户下载。

总之,Blob 是一个非常灵活且强大的工具,用来处理各种类型的数据,尤其是在需要本地存储或快速操作数据时非常有用。

添加到blob,并下载

javascript 复制代码
const download = async (row, index) => {
	// ... 获取一个blob。如果是多个视频,就是多个blob
	const zipContent = [
		{
			blob,
			videoContent: row.videoContent,
		},
	];
	saveAsZip(zipContent, row.s_title);
};
javascript 复制代码
const saveAsZip = async (files: ZIPContent[], title) => {
	// 新增一个zip文件
	const zip = new JSZip();

	// 将所有文件添加到 ZIP 文件中
	files.forEach((item: ZIPContent) => {
		const blob = item.blob;
		const videoContent = item.videoContent;
		const fileName = `${title} - 第${videoContent}集.${blob.type.split("/")[1]}`; // 根据 MIME 类型推断文件扩展名

		// 在zip中新增文件
		zip.file(fileName, blob);
	});

	// 生成 ZIP 文件的 Blob
	const zipBlob = await zip.generateAsync({
		type: "blob",
		compression: "DEFLATE", // 使用 DEFLATE 压缩
		compressionOptions: { level: 9 }, // 压缩级别(0-9)
	});

	// 下载 ZIP 文件
	saveAs(zipBlob, `${title}.zip`);
};

实测可以下载。

其他

页面预加载视频

服务端下发视频url后,把所有url都生成为blobUrl。不要在点击【预览】的时候才生成blobUrl。

页面预览视频:blobUrl

如果想要生成一个blob的url,如用于视频的播放:

javascript 复制代码
const blob = await (await fetch(url)).blob();
const blobUrl = URL.createObjectURL(blob);
currentUrl.value = blobUrl;

则可以使用URL.createObjectURL生成url

强制视频元素重新加载

如果在页面中可以预览视频的上下集,在切换了上下集后,currentUrl更新,需要强制视频元素重新加载:

html 复制代码
<div v-if="currentUrl && currentUrl.length">
	<video
		ref="videoRef"
		style="text-align: center; width: 100%; height: 300px"
		controls
		autoplay
		muted
		preload="metadata"
	>
		<source
			:src="currentUrl"
			:key="currentIndex"
			type="video/mp4"
		/>
		您的浏览器不支持 video 标签。
	</video>
</div>
<div v-else>暂无视频</div>
javascript 复制代码
const videoRef = ref<HTMLVideoElement>();
const handleVideoLoad = () => {
	// 强制视频元素重新加载
	if (videoRef.value) {
		videoRef.value.pause();
		videoRef.value.currentTime = 0;
		videoRef.value.load();
	}
};

多选视频并下载到zip

需要注意:forEach不会等待异步,因此需要用for

javascript 复制代码
await ElMessageBox.confirm("确认批量下载选中剧集?", "批量下载操作").then(
	async () => {
		const files: ZIPContent[] = [];
		// 使用 for 循环处理异步操作:forEach不支持异步
		for (let i = 0; i < multipleSelection.value.length; i++) {
			const item = multipleSelection.value[i]; // table多选的列表
			const index = tableData.value.list.findIndex(
				(dataItem) => dataItem.videoContent === item.videoContent
			);
			// 异步获取Blob文件
			const blob = await getBlob(index, item);
			files.push({
				blob,
				videoContent: item.videoContent,
			});
		}
		// 下载
		saveAsZip(files, multipleSelection.value[0].s_title);

		// 清空选中列表
		clearSelection();
	}
);
相关推荐
一枚前端小能手3 分钟前
💫 回调套回调写到崩溃,异步编程其实可以很优雅
前端·javascript
用户479492835691514 分钟前
深入理解JavaScript:手写实现Array.prototype.push方法
前端·javascript
前端Hardy18 分钟前
HTML&CSS&JS:卡片3D倾斜效果
前端·javascript·css
lichenyang45321 分钟前
从0开始的中后台管理系统-5(菜单的路径绑定以及角色页面的实现)
前端
前端Hardy23 分钟前
HTML&CSS&JS:一键登录页面
前端·javascript·css
VUE41 分钟前
借助ai半小时设计出来一款获取图片自动填充路径的mcp插件
前端·javascript·mcp
kymjs张涛1 小时前
零一开源|前沿技术周刊 #11
前端·javascript·vue.js
会是上一次1 小时前
企业级WEB应用服务器TOMCAT
java·前端·tomcat
anyup1 小时前
🚀 2025 最推荐的 uni-app 技术栈:unibest + uView Pro 高效开发全攻略
前端·vue.js·uni-app
小喷友1 小时前
第 12 章:最佳实践与项目结构组织
前端·react.js·next.js