当前位置: 首页 > news >正文

休闲文化网站深圳网络推广培训中心

休闲文化网站,深圳网络推广培训中心,网页传奇辅助,湖南长沙网站建设公司电话切片上传的原理是: 1.因为file对象的基类是blob,所以可以使用slice分割 2.将从input中获取的file对象使用slice进行分割,每5M一片 3.分别上传各个切片,等待切片上传完通知服务端合并(或者传每一片时把切片总数量也传…

切片上传的原理是:

1.因为file对象的基类是blob,所以可以使用slice分割

2.将从input中获取的file对象使用slice进行分割,每5M一片

3.分别上传各个切片,等待切片上传完通知服务端合并(或者传每一片时把切片总数量也传递过去,让服务端自行合并)

断点续传原理:

切片上传完成之后将上传完的索引放到localStrage上,再次上传时判断是否上传,如果已经上传了则跳过这一片

实现代码:

这里是主进程👇

import { getFileId } from './utils/FileUtils'
import { getLocalStrage, setLocalStrage, removeLocalStrage } from './utils/localStrage'
const worker = new Worker(new URL('./uploadWorker.js', import.meta.url))// 监听WebWorker的消息
worker.onmessage = (e) => {const { type, data, filename, fileId, uploadInfo } = e.dataif (type === 'progress') {document.getElementById('progress').innerHTML = `当前上传进度:${data}%`// 更新切片上传日志setLocalStrage(fileId, JSON.stringify(uploadInfo))} else if (type === 'complete') {document.getElementById('progress').innerHTML = `上传完毕!`worker.postMessage({type: 'merge',filename: filename,})// 移除切片上传日志removeLocalStrage(fileId)}
}// 监控用户上传数据
const upload = document.getElementById('fileInput')upload?.addEventListener('change', async (e) => {const file = e?.target?.files?.[0]const fileId = await getFileId(file)const infoLocal = getLocalStrage(fileId)const uploadInfo = infoLocal  ? JSON.parse(infoLocal) : {fileId: fileId,fileName: file.name,uploadedChunks: [],}worker.postMessage({type: 'upload',file,fileId: fileId,uploadInfo: uploadInfo})
})

这里是工作进程👇

const CHUNK_SIZE = 1024 * 1024 * 5 // 5MBlet uploadInfo = null;// 建通主线程的消息
self.onmessage = (e) => {console.log('收到主线程的消息')const { type, file, filename, fileId, uploadInfo: uploadInfoLocal } = e.dataif (type === 'upload') {// 初始化上传信息uploadInfo = uploadInfoLocal// 开始上传文件uploadFile(file, fileId)} else if (type === 'merge') {mergeFile(filename)}
}// 切片上传文件
function uploadFile(file, fileId) {const fileName = file.name// 获取thunk的数量const chunksCount = Math.ceil(file.size / CHUNK_SIZE)// 获取切片数据const chunks = getChunks(file)uploadQueueChunks(chunks, fileName, chunksCount, fileId)
}/*** 获取切片数据* @param file * @returns */
function getChunks(file) {const chunks = []for(let i = 0; i < file.size; i += CHUNK_SIZE) {chunks.push(file.slice(i, i + CHUNK_SIZE))}return chunks
}/*** 上传队列* @param chunks 切片数据* @param fileName 文件名* @param chunksCount 总切片数* @param maxConcurrency 最大并发数*/
async function uploadQueueChunks(chunks, fileName, chunksCount, fileId, maxConcurrency = 5) {// 正在上传的队列const queue = []// 正在上传的文件数量let activeUploads = 0// 遍历上传切片for(let i = 0; i < chunks.length; i++) {// 如果上传过了就直接跳过if(uploadInfo.uploadedChunks.indexOf(i) > -1) {console.log(`第${i}片已经上传过了`)continue}const chunk = chunks[i]// 判断当前上传队列是否达到最大并发if(activeUploads >= maxConcurrency) {// 等待队列中上传完成await Promise.race(queue)}// 上传切片const uploadPromise = uploadedChunk(chunk, i, fileName, chunksCount).then(res=> {// 上传完成,从队列中移除queue.splice(queue.indexOf(uploadPromise), 1)// 更新上传信息uploadInfo.uploadedChunks.push(i)// 减少正在上传的数量activeUploads--// 发送上传进度self.postMessage({type: 'progress',data: Math.round((uploadInfo.uploadedChunks.length / chunksCount) * 100),filename: fileName,uploadInfo: uploadInfo,fileId});})queue.push(uploadPromise)activeUploads++}await Promise.all(queue)// 发送完成通知self.postMessage({type: 'complete',filename: fileName,fileId});
}/*** 上传切片数据* @param thunk 切片数据* @param index 切片索引* @param name 文件名* @param total 总切片数*/
function uploadedChunk(thunk, index, name, total) {console.log(`上传第${index}片`)const formData = new FormData()formData.append('file', thunk)formData.append('index', index.toString())formData.append('filename', name)formData.append('totalChunks', total)return fetch('http://localhost:3000/upload', {method: 'POST',body: formData})
}function mergeFile(filename) {console.log(`开始合并文件:${filename}`)return fetch(`http://localhost:3000/merge`, {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ filename })})
}

这里是工具类

/*** 获取文件唯一ID* @param {*} file * @returns */
export async function getFileId(file) {const buffer = await file.arrayBuffer();const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);const hashArray = Array.from(new Uint8Array(hashBuffer));return hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');}export function getLocalStrage(fileId) {return localStorage.getItem(fileId);
}export function setLocalStrage(fileId, data) {return localStorage.setItem(fileId, data);
}export function removeLocalStrage(fileId) {return localStorage.removeItem(fileId);
}

文件目录是这样的👇

就能实现下面的效果:

http://www.dinnco.com/news/25205.html

相关文章:

  • 成都新津网站建设google推广 的效果
  • 个人做网站用什么技术品牌网络营销成功案例
  • 网站怎样做推广计划百度推广电话销售好做吗
  • 夏津网站开发搜索引擎营销的手段包括
  • 东莞网站建设企业搜索引擎营销的特点
  • 武汉做网站冰洁找到冰洁工作室杭州互联网公司排名榜
  • 有名的互联网公司免费关键词优化排名软件
  • 孝感做网站有哪些免费网站可以发布广告
  • 遵义市汇川区建设厅网站深圳关键词优化怎么样
  • 长锦船公司网站新的数据新闻
  • 四大门户网站是哪些seo深圳培训班
  • 柳州网站建设服务石家庄关键词排名首页
  • 郑州广告公司网站建设百度普通版下载
  • wordpress z合肥网站seo公司
  • 网站建设域名怎么选择重庆网站seo推广公司
  • 美容院装修seo排名优化技术
  • 武汉光谷做网站多少钱网站自然优化
  • 网站怎么做才吸引人今日头条普通版
  • 批发购物网站建设谷歌搜索广告优化
  • 旅游网站如何做西安计算机培训机构哪个最好
  • 长沙微网站电话号码武汉seo网站管理
  • 网站建设资讯版块如何做用户运营百度自己的宣传广告
  • 最火网站排名北京网站快速优化排名
  • 苍南规划建设局网站seo推广费用需要多少
  • 广州专业网站改版领军企业收录之家
  • 网站建设与规划实训总结百度一下搜索引擎
  • 网站维护工作关键词搜索排名软件
  • 五月色做受网站最有效的网络推广方式和策略
  • 哪些网站的登陆界面做的好看响应式模版移动优化
  • 吉林省建设厅网站手机自己怎么建电影网站