// 简单的页面布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<p>
<progress id="uploadProgress" value="0"></progress>
</p>
<p>
<input type="file" id="videoUploader" value="选择视频" />
</p>
<p>
<span id="uploadInfo"></span>
</p>
<p>
<button id="uploadBtn">上传视频</button>
</p>
</div>
<video></video>
</body>
<script src="./app.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</html>
// 大文件切片上传---js逻辑
// 设置地址
const BASE_URL = 'http://localhost:8080/';
// 定义一些提示信息
const UPLOAD_INFO = {
'NO_FILE': '请选择文件',
'INVALID_TYPE': '上传文件的格式不对',
'UPLOAD_FAILED': '上传失败',
'UPLOAD_SUCCESS': '上传成功'
};
// 定义符合的格式
const ALLOWED_TYPE = {
'video/mp4': 'mp4',
'video/ogg': 'ogg'
};
// 设置要切割文件的大小
const CHUNK_SIZE = 64 * 1024;
// 设置axios的接口
const API = {
UPLOAD_VIDEO: BASE_URL + 'upload_video'
}
; ((doc) => {
// 获取进度条
const oProgress = doc.querySelector('#uploadProgress');
// 获取上视频
const oUpLoader = doc.querySelector('#videoUploader');
// 获取提交信息标签
const oInfo = doc.querySelector('#uploadInfo');
// 获取提交button
const oBtn = doc.querySelector('#uploadBtn');
// 定义上传的初始值
let uploadedSize = 0;
// 初始化操作
const init = () => {
//调用绑定提交事件函数
bindEvent();
};
// 绑定提交事件
function bindEvent() {
oBtn.addEventListener('click', uploadVideo, false);
};
// 处理文件的函数
async function uploadVideo() {
// 获取上传的视频的一些信息
const { files: [file] } = oUpLoader;
// 判断是否上传文件
if (!file) {
// 提示
oInfo.innerText = UPLOAD_INFO['NO_FILE'];
return;
};
// 判断上传的文件格式是否符合要求(file里面有一个type属性是查看上传视频的格式)
if (!ALLOWED_TYPE[file.type]) {
// 提示
oInfo.innerText = UPLOAD_INFO['INVALID_TYPE'];
return;
};
// 从file中提取出name type size
const { name, type, size } = file;
// 设置一个fileName 这样写只是为了测试 开发中不建议
const fileName = new Date().getTime() + '-' + name;
// 声明一个用来接受请求的结果
let uploadedResult = null;
// 给进度条设置最大值
oProgress.max = size;
// 清空提示信息里面的内容
oInfo.innerText = '';
//循环切割 如果小于文件大小就一直切割
while (uploadedSize < size) {
// 开始切割
const fileChunk = file.slice(uploadedSize, uploadedSize + CHUNK_SIZE);
// 调用函数且传参
const formData = createFormData({
name,
type,
size,
fileName,
uploadedSize,
file: fileChunk
});
// 发送上传请求
try {
uploadedResult = await axios.post(API['UPLOAD_VIDEO'], formData);
} catch (error) {
oInfo.innerText = UPLOAD_INFO['UPLOAD_FAILED'] + error.message;
return;
}
// 给上传大小重新赋值
uploadedSize += fileChunk.size;
// 进度条等于上传大小
oProgress.value = uploadedSize;
};
// 最后提示上传成功
oInfo.innerText = UPLOAD_INFO['UPLOAD_SUCCESS'];
// 清空数据
oUpLoader.value = null;
// 创建视图
createVideo(uploadedResult.data.video_url);
// debugger
return;
};
// 创建函数分装需要上传的东西
function createFormData({
name,
type,
size,
fileName,
uploadedSize,
file
}) {
// 创建formData
const fd = new FormData();
fd.append('name', name);
fd.append('type', type);
fd.append('size', size);
fd.append('fileName', fileName);
fd.append('uploadedSize', uploadedSize);
fd.append('file', file);
return fd;
}
function createVideo(src) {
const oVideo = document.createElement('video');
oVideo.controls = true;
oVideo.width = '500';
oVideo.src = src;
document.body.appendChild(oVideo);
// debugger
}
//调用初始化
init();
})(document);
// 大文件上传---node.js (1.npm init --yes 2.npm i express 3.创建upload_temp 保存传过来的视频)
const express = require('express');
const app = express();
// 处理文件
const uploader = require('express-fileupload');
// 解析body
var bodyParser = require('body-parser');
// 帮助我们转化类型的
const { extname, resolve } = require('path');
// 帮助我们写文件 追加文件 和 编文件
const { existsSync, appendFileSync, writeFileSync } = require('fs');
// 使用
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// 使用
app.use(uploader());
// 设置访问静态文件
app.use('/', express.static('upload_temp'));
const ALLOWED_TYPE = {
'video/mp4': 'mp4',
'video/ogg': 'ogg'
}
// 设置容许跨域
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-origin', '*');
res.header('Access-Control-Allow-Methods', 'POST,GET');
next();
});
// 配置接口
app.post('/upload_video', (req, res) => {
// 从req.body里面结构出以下
const {
name,
type,
size,
fileName,
uploadedSize
} = req.body;
// 从files里面结构出file
const { file } = req.files
// 判断里面是否有file属性
if (!file) {
res.send({
code: 1001,
msg: 'No file uploaded'
});
return;
};
// 判断是否符合上传的类型
if (!ALLOWED_TYPE[type]) {
res.send({
code: 1002,
msg: 'The type not allowed for uploading.'
});
return;
};
// 转化类型 利用path里面的extname方法进行拼接转化
const filename = fileName + extname(name);
const filePath = resolve(__dirname, './upload_temp/' + filename)
// 判断uploadeSize是否等于0
if (uploadedSize !== '0') {
if (!existsSync(filePath)) {
res.send({
code: 1003,
msg: 'No file exists'
});
return;
}
// 追加file.data
appendFileSync(filePath, file.data);
res.send({
code: 0,
msg: 'Appended',
video_url: 'http://localhost:8080/' + filename
});
return;
};
// 如果以上条件都没有符合的话 我们就写入
writeFileSync(filePath, file.data);
// 发送写完
res.send({
code: 0,
msg: 'File is created'
});
});
// 配置端口号
const POST = 8080;
// 启动
app.listen(POST, () => {
console.log('服务已经启动...');
});
大文件切片上传---node+js
最新推荐文章于 2024-04-21 12:14:17 发布