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

成都青白江网站建设网络推广怎么找客户资源

成都青白江网站建设,网络推广怎么找客户资源,阿里巴巴做网站费用,确保网站建设又在前列目录 1.最简单的文件上传 2.拖拽粘贴样式优化 3.断点续传秒传进度条 文件切片 计算hash 断点续传秒传(前端) 断点续传秒传(后端) 进度条 4.抽样hash和webWorker 抽样hash(md5) webWorker 时间切片 5.文件类型判断 通过文件头判断文件类型 6.异步并发数控制(重要…目录 1.最简单的文件上传 2.拖拽粘贴样式优化 3.断点续传秒传进度条 文件切片 计算hash 断点续传秒传(前端) 断点续传秒传(后端) 进度条 4.抽样hash和webWorker 抽样hash(md5) webWorker 时间切片 5.文件类型判断 通过文件头判断文件类型 6.异步并发数控制(重要) 7.并发错误重试 8.慢启动控制 9.碎片清理 后记 参考资料 本文适合有一定node后端基础的前端同学,如果对后端完全不了解请恶补前置知识。 废话不多说,直接进入正题。 我们来看一下,各个版本的文件上传组件大概都长什么样 等级功能青铜-垃圾玩意原生axios.post白银-体验升级粘贴,拖拽,进度条黄金-功能升级断点续传,秒传,类型判断铂金-速度升级web-worker,时间切片,抽样hash钻石-网络升级异步并发数控制,切片报错重试王者-精雕细琢慢启动控制,碎片清理等等 1.最简单的文件上传 文件上传,我们需要获取文件对象,然后使用formData发送给后端接收即可 function upload(file){let formData  new FormData();formData.append(newFile, file);axios.post(http://localhost:8000/uploader/upload,formData, { headers: { Content-Type: multipart/form-data } }) } 2.拖拽粘贴样式优化 懒得写,你们网上找找库吧,网上啥都有,或者直接组件库解决问题 3.断点续传秒传进度条 文件切片 我们通过将一个文件分为多个小块,保存到数组中.逐个发送给后端,实现断点续传。 // 计算文件hash作为id const { hash }  await calculateHashSample(file) //todo 生成文件分片列表  // 使用file.slice()将文件切片 const fileList  []; const count  Math.ceil(file.size / globalProp.SIZE); const partSize  file.size / count; let cur  0  // 记录当前切片的位置 for (let i  0; i  count; i) {let item  { chunk: file.slice(cur, cur  partSize), filename: ${hash}_${i}};fileList.push(item); } 计算hash 为了让后端知道,这个切片是某个文件的一部分,以便聚合成一个完整的文件。我们需要计算完整file的唯一值(md5),作为切片的文件名。 // 通过input的event获取到file input typefile changegetFile// 使用SparkMD5计算文件hash,读取文件为blob,计算hash let fileReader  new FileReader();fileReader.onload  (e) {let hexHash  SparkMD5.hash(e.target.result);console.log(hexHash);  }; 断点续传秒传(前端) 我们此时有保存了100个文件切片的数组,遍历切片连续向后端发送axios.post请求即可。设置一个开关实现启动-暂停功能。 如果我们传了50份关掉了浏览器怎么办 此时我们需要后端配合在上传文件之前先检查一下后端接收了多少文件。 当然如果发现后端已经上传过这个文件直接显示上传完毕(秒传) // 解构出已经上传的文件数组 文件是否已经上传完毕  // 通过文件hash和后缀查询当前文件有多少已经上传的部分 const {isFileUploaded, uploadedList}  await axios.get(http://localhost:8000/uploader/count ?hash${hash}         suffix${fileSuffix} ) 断点续传秒传(后端) 至于后端的操作就比较简单了 根据文件hash创建文件夹保存文件切片 检查某文件的上传情况通过接口返回给前端 例如以下文件切片文件夹 //! --------通过hash查询服务器中已经存放了多少份文件(或者是否已经存在文件)------ function checkChunks(hash, suffix) { //! 查看已经存在多少文件 获取已上传的indexList const chunksPath  ${uploadChunksDir}${hash};const chunksList  (fs.existsSync(chunksPath)  fs.readdirSync(chunksPath)) || []; const indexList  chunksList.map((item, index) item.split(_)[1]) //! 通过查询文件hashsuffix 判断文件是否已经上传 const filename  ${hash}${suffix}const fileList  (fs.existsSync(uploadFileDir)  fs.readdirSync(uploadFileDir)) || []; const isFileUploaded  fileList.indexOf(filename)  -1 ? false : true console.log(已经上传的chunks, chunksList.length); console.log(文件是否存在, isFileUploaded); return { code: 200,data: { count: chunksList.length, uploadedList: indexList, isFileUploaded: isFileUploaded}} }进度条 实时计算一下已经成功上传的片段不就行了自行实现吧 4.抽样hash和webWorker 因为上传前我们需要计算文件的md5值作为切片的id使用。md5的计算是一个非常耗时的事情如果文件过大js会卡在计算md5这一步造成页面长时间卡顿。 我们这里提供三种思路进行优化 抽样hash(md5) 抽样hash是指我们截取整个文件的一部分计算hash提升计算速度。 1. 我们将file解析为二进制buffer数据, 2. 抽取文件头尾2mb, 中间的部分每隔2mb抽取2kb 3. 将这些片段组合成新的buffer,进行md5计算。 图解: 样例代码 //! ---------------抽样md5计算------------------- function calculateHashSample(file) {return new Promise((resolve)  {//!转换文件类型解析为BUFFER数据 用于计算md5const spark  new SparkMD5.ArrayBuffer();const { size }  file;const OFFSET  Math.floor(2 * 1024 * 1024); // 取样范围 2Mconst reader  new FileReader();let index  OFFSET;// 头尾全取中间抽2字节const chunks  [file.slice(0, index)];while (index  size) {if (index  OFFSET  size) {chunks.push(file.slice(index));} else {const CHUNK_OFFSET  2;chunks.push(file.slice(index, index  2),file.slice(index  OFFSET - CHUNK_OFFSET, index  OFFSET));}index  OFFSET;}// 将抽样后的片段添加到sparkreader.onload  (event)  {spark.append(event.target.result);resolve({hash: spark.end(),//Promise返回hash});}reader.readAsArrayBuffer(new Blob(chunks));}); } webWorker 除了抽样hash我们可以另外开启一个webWorker线程去专门计算md5。 webWorker: 就是给JS创造多线程运行环境允许主线程创建worker线程分配任务给后者主线程运行的同时worker线程也在运行相互不干扰在worker线程运行结束后把结果返回给主线程。 具体使用方式可以参考MDN或者其他文章 使用 Web Workers \- Web API 接口参考 | MDN \(mozilla.org\)[1] 一文彻底学会使用web worker \- 掘金 \(juejin.cn\)[2] 时间切片 熟悉React时间切片的同学也可以去试一试不过个人认为这个方案没有以上两种好。 不熟悉的同学可以自行掘金一下文章还是很多的。这里就不多做论述只提供思路。 时间切片也就是传说中的requestIdleCallbackrequestAnimationFrame 这两个API了或者高级一点自己通过messageChannel去封装。 切片计算hash将多个短任务分布在每一帧里减少页面卡顿。 5.文件类型判断 简单一点,我们可以通过input标签的accept属性,或者截取文件名来判断类型 input idfile typefile acceptimage/* /const ext  file.name.substring(file.name.lastIndexOf(.)  1); 当然这种限制可以简单的通过修改文件后缀名来突破并不严谨。 通过文件头判断文件类型 我们将文件转化为二进制blob文件的前几个字节就表示了文件类型我们读取进行判断即可。 比如如下代码 // 判断是否为 .jpg  async function isJpg(file) {// 截取前几个字节,转换为stringconst res  await blobToString(file.slice(0, 3))return res  FF D8 FF } // 判断是否为 .png  async function isPng(file) {const res  await blobToString(file.slice(0, 4))return res  89 50 4E 47 } // 判断是否为 .gif  async function isGif(file) {const res  await blobToString(file.slice(0, 4))return res  47 49 46 38 } 当然咱们有现成的库可以做这件事情,比如 file-type 这个库 file-type \- npm \(npmjs.com\)[3] 6.异步并发数控制(重要) 我们需要将多个文件片段上传给后端总不能一个个发送把我们这里使用TCP的并发实现控制并发进行上传。 首先我们将100个文件片段都封装为axios.post函数存入任务池中 创建一个并发池同时执行并发池中的任务发送片段 设置计数器i当i并发数时才能将任务推入并发池 通过promise.race方法 最先执行完毕的请求会被返回 即可调用其.then方法 传入下一个请求(递归) 当最后一个请求发送完毕 向后端发起请求 合并文件片段 图解 代码 //! 传入请求列表  最大并发数  全部请求完毕后的回调 function concurrentSendRequest(requestArr: any, max  3, callback: any) {let i  0 // 执行任务计数器let concurrentRequestArr: any[]  [] //并发请求列表let toFetch: any  ()  {// (每次执行i1) 如果iarr.length 说明是最后一个任务  // 返回一个resolve 作为最后的toFetch.then()执行// (执行Promise.all() 全部任务执行完后执行回调函数  发起文件合并请求)if (i  requestArr.length) {return Promise.resolve()}//TODO 执行异步任务  并推入并发列表(计数器1)let it  requestArr[i]()concurrentRequestArr.push(it)//TODO 任务执行后  从并发列表中删除it.then(()  {concurrentRequestArr.splice(concurrentRequestArr.indexOf(it), 1)})//todo 如果并发数达到最大数则等其中一个异步任务完成再添加let p  Promise.resolve()if (concurrentRequestArr.length  max) {//! race方法 返回fetchArr中最快执行的任务结果 p  Promise.race(concurrentRequestArr)}//todo race中最快完成的promise,在其.then递归toFetch函数if (globalProp.stop) { return p.then(()  { console.log(停止发送) }) }return p.then(()  toFetch())}// 最后一组任务全部执行完再执行回调函数(发起合并请求)(如果未合并且未暂停)toFetch().then(() Promise.all(concurrentRequestArr).then(()  {if (!globalProp.stop  !globalProp.finished) { callback() }})) }7.并发错误重试 使用catch捕获任务错误上述axios.post任务执行失败后重新把任务放到任务队列中 给每个任务对象设置一个tag记录任务重试的次数 如果一个切片任务出错超过3次直接reject。并且可以直接终止文件传输 8.慢启动控制 由于文件大小不一我们每个切片的大小设置成固定的也有点略显笨拙我们可以参考TCP协议的慢启动策略。设置一个初始大小根据上传任务完成的时候来动态调整下一个切片的大小 确保文件切片的大小和当前网速匹配。 ·chunk中带上size值不过进度条数量不确定了修改createFileChunk 请求加上时间统计 ·比如我们理想是30秒传递一个。初始大小定为1M如果上传花了10秒那下一个区块大小变成3M。如果上传花了60秒那下一个区块大小变成500KB 以此类推 9.碎片清理 如果用户上传文件到一半终止并且以后也不传了后端保存的文件片段也就没有用了。 我们可以在node端设置一个定时任务setInterval,每隔一段时间检查并清理不需要的碎片文件。 可以使用 node-schedule 来管理定时任务比如每天检查一次目录如果文件是一个月前的那就直接删除把。 垃圾碎片文件 后记 以上就是一个完整的比较高级的文件上传组件的全部功能希望各位有耐心看到这里的新手小伙伴能够融会贯通。每天进步一点点。 参考资料 [1] https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers: https://link.juejin.cn?targethttps%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FWeb_Workers_API%2FUsing_web_workers [2] https://juejin.cn/post/7139718200177983524: https://juejin.cn/post/7139718200177983524 [3] https://www.npmjs.com/package/file-type: https://link.juejin.cn?targethttps%3A%2F%2Fwww.npmjs.com%2Fpackage%2Ffile-type
http://www.sczhlp.com/news/189024/

相关文章:

  • 网站建设原因盘锦建设信息网站
  • 济南专业做网站什么网站可以做十万的分期付款
  • 域名备案网站名称网络维护的基本内容有哪些
  • 代发货网站建设江苏优化网站价格
  • 什么是网站主题域名服务器作用
  • 做网站的空间要多大的怎样设计一个网页页面
  • 西安公积金 网站建设怎样用jsp做网站登录
  • 手机网站标准字体大小wordpress 微信发布文章
  • 做足球预测的网站手机欧美视频网站模板下载 迅雷下载地址
  • 网站建设的成本有哪些方面广东中高风险地区最新名单
  • 占位符
  • 什么是IO多路复用?
  • 阻塞、非阻塞、同步、异步的区别是什么?
  • 如何防范员工泄露数据给 AI?2025年选型与落地实战版
  • 做公司网站都需要什么资料太原新建火车站
  • 沈阳学校网站建设seo视频教程汇总
  • ui做套网站多少钱月夜直播视频免费观看
  • 教育机构网站建设方案书杭州建站模板制作
  • wordpress页面回收站flash类网站开发
  • 厦门网站建设 智多星温州网站建站模板
  • 侧导航网站小公司做网站的实力
  • 做思维导图的网站简述jsp网站架构
  • 措美网站建设拼多多网络营销方式
  • 深圳模板网站多少钱wordpress模板 图片站
  • 简约风格网站建设wordpress加图片不显示
  • 优秀网站架构检查色盲效果网站
  • 单页营销网站后台网络服务推广易下拉技巧
  • 网站服务器要求锐酷网站建设教程
  • 网站开发人员岗位建设通网站源码
  • wordpress转移整站win7系统优化工具