大文件上传,参考地址demo:gitee.com/chenganglon…
1.认识大文件上传(是什么?)
大文件一般是指占用内存空间比较大的文件,比如我们下载的小电影,MV,4k的高清图片等等,一般把100MB以上的文件称为大文件
2.为什么要做大文件上传(为什么?)
如果一个文件有足够大的时候,用户等待的时间可能还做各种的操作,比如等待,取消下载,甚至关闭整个浏览器,这些操作都影响我们的存储,我到底是把用户上传的东西存下来呢还是不存呢,这个就没有一个明确的规定了
3.怎么做大文件上传(怎么做?)
1.大文件上传主要是对某个文件的空间进行slice()的切割,我们称为切片上传
前端:
1.点击上传的时候,首先要判断,file中有没有放东西上去,其次要判断上传文件的类型
2.做上传逻辑,就是把在 const file = videoUploader.files[0]中的file的 name size type丢给后端
3.切片上传
while(uploadSize < size){
const fileChunk = file.slice(uploadSize, uploadSize + CHUNK_SIZE);
}
循环请求,在本地保留文件的大小 与 本文件的大小进行比较
const BASEURL = 'http://localhost:8000/';
export const UPLOAD_INFO = {
'NO_files':'请选择文件上传',
'FileTypeError':'不支持类型上传',
'FileTypeSuccess':'上传成功',
'upload_Error':'上传失败'
}
export const ALLOW_TYPE = {
"image/png":'png',
"video/mp4":'mp4'
}
// 64K
export const CHUNK_SIZE = 64 * 1024
// API路径
export const API ={
URL:BASEURL + 'upload_video'
}
import {UPLOAD_INFO, ALLOW_TYPE, CHUNK_SIZE,API} from './config'
import axios from 'axios'
;((doc)=>{
const uploadProgress = doc.querySelector('#uploadProgress');
const videoUploader = doc.querySelector('#videoUploader');
const uploadInfo = doc.querySelector('#uploadInfo');
const uploadBtn = doc.querySelector('#uploadBtn');
// 保留上传的大小
let uploadSize = 0;
const init = () => {
bindEvent();
}
function bindEvent() {
uploadBtn.addEventListener('click',uploadVideo,false);
}
async function uploadVideo() {
const file = videoUploader.files[0];
// file没上传为undefined
if(!file){
uploadInfo.innerText = UPLOAD_INFO['NO_files'];
return;
}
// 判断上传文件的类型
if( !ALLOW_TYPE[file.type] ){
uploadInfo.innerText = UPLOAD_INFO['FileTypeError']
}else{
uploadInfo.innerText = UPLOAD_INFO['FileTypeSuccess'] + 1
}
// 上传逻辑 name size type
const { name, size ,type } = file
const fileName = new Date().getTime() + name
uploadProgress.max = size
while(uploadSize < size){
const fileChunk = file.slice(uploadSize, uploadSize + CHUNK_SIZE);
const formData = createFormData({name, size ,type,fileName,uploadSize,file:fileChunk})
// 发请求到后端
try{
const res = await axios.post(API.URL,formData)
console.log(res.data.data)
} catch(e){
uploadInfo.innerText = `${UPLOAD_INFO['upload_Error']}(${e})`
return
}
uploadSize += fileChunk.size
uploadProgress.value = uploadSize
}
uploadInfo.innerText = UPLOAD_INFO['FileTypeSuccess'] + 2
videoUploader.value = null
}
function createFormData( {name, size ,type,fileName,uploadSize,file} ){
const fd = new FormData()
fd.append('name' , name);
fd.append('size' , size);
fd.append('type' , type);
fd.append('fileName' , fileName);
fd.append('uploadSize' , uploadSize);
fd.append('file' , file);
return fd
}
init();
})(document);
后端:
const express = require('express')
const bodyParser = require('body-parser')
const upload = require('express-fileupload')
// 获取后缀
const { extname,resolve } = require('path')
const { existsSync,appendFileSync,writeFileSync } = require('fs')
const app = express()
app.use(bodyParser.urlencoded({ extended:true }))
app.use(bodyParser.json())
app.use(upload())
app.use('/',express.static('upload'))
// 处理跨域
app.all('*',(req, res, next)=>{
res.header('Access-Control-Allow-origin','*');
res.header('Access-Control-Allow-Methods','POST,GET');
next()
})
const ALLOW_TYPE = {
"image/png":'png',
"video/mp4":'mp4'
}
app.post('/upload_video',(req, res)=>{
// 接受到前端的少了file
// const { name, size ,type,fileName,uploadSize } = req.body
// // 获取file
// const { file } = req.files
// if( !file ){
// res.send({
// code:1001,
// msg:'未上传文件'
// })
// return
// }
// // 判断类型(安全)
// if( !ALLOW_TYPE[type] ){
// res.send({
// code:1002,
// msg:'文件类型不支持'
// })
// return
// }
// // 文件名
// const filename = fileName + extname(name);
// // 获取文件夹路径
// const filePath = resolve(__dirname,'./upload/' + filename )
// if( uploadSize !== '0' ) {
// if( !existsSync(filePath) ){
// res.send({
// code:1003,
// msg:'文件类型不存在'
// })
// return
// }
// appendFileSync( filePath,file.data )
// res.send({
// code:0,
// msg:'Appended',
// data:{
// video_url:'http://localhost:8000/' + filename
// }
// })
// return
// }
// // 文件存在
// writeFileSync(filePath,file.data)
// res.send({
// code:0,
// msg:'File is created'
// })
})
const PORT = 8000
app.listen(PORT ,() => {
console.log( 'server in the http://localhost:8000/upload_video' )
})