js blob 文件上传

js blob 文件上传

js中的文件处理和文件上传掌握得更扎实,有更深入的理解,底层原理

ps.项目中使用插件上传

  • filereader
  • mime类型筛选
  • 单文件的2种处理方案
  • 多文件&文件上传进度管控

Ajax文件上传时:Formdata、File、Blob的关系-腾讯云开发者社区-腾讯云

Js上传blob_js blob上传_js blob 上传图片 - 腾讯云开发者社区 - 腾讯云

文件上传基础知识

filereader:异步读取和解析文件

通过input-type="file"元素获取到files列表file对象有3个基础属性:

+name

+size:xxx字节 xxxB

+type: mime类型

缩略图:

FileReader实例读取到base64编码readAsDataUrl

readAsArrayBuffer:读取到的arraybuffer或者是blob对象,大文件切片上传的时候

上传到服务器-formdata

上传中:有个loading效果

缩略图是:上传到服务器之后服务器上的地址

axios封装

面试时经常问——客户端传给服务器端的格式:

multipart/form-data、application/json、application/x-www-form-urlencoded(表单形式:xxx=xxx&xxx=xxx)、raw(纯文本、json、二进制)=====》MIME类型和请求头配置

待解决服务器:

起一个node服务:用那个库multipart

跨域 

javascript - node中multiparty模块使用form.parse解析上传文件时回调函数参数files获取为空对象 - SegmentFault 思否

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件title>
    <style>

    style>
head>
<body>
<input type="file" id="uploadFile" accept="image/*">
<img src="" alt="" width="100" id="uploadImg">
<script src="./js/axios.min.js">script> <script src="./js/qs.min.js">script> <script> uploadFile.onchange=async function (){ let files=this.files; if(!files.length) return; /** * name * size * type:mime类型 */ // 校验类型:只允许上传图片 let file=files[0]; let {name,size,type}=file; if(!/(jpg|png|jpeg|gif)$/.test(type)) return alert('只能上传jpg|png|jpeg|gif格式') if(size>1024*1024) return alert('文件大小不能超过1MB') console.log('file',file); /** * 缩略图:通过fileReader去读取图片,得到base64编码 */ /*let fileReader=new FileReader() // readAsArrayBuffer 读取成buffer或者blob格式的值。断点续传/切片上传 fileReader.readAsDataURL(file); fileReader.onload=function (ev){ console.log('ev',ev); uploadImg.src=ev.target.result; }*/ /** * 1.form-data方法,把完整的file对象传过去 */ /*let formData=new FormData() formData.append('file',file) formData.append('filename',file.name); console.log(formData,formData.get('file'),formData.get('filename')); let res=await postRequest('/upload1',formData,{headers:{'Content-Type':'multipart/form-data'}}); uploadImg.src=res.path;*/ /** * 2.base64方法 */ let base64=await readBase64(file) let data={ chunk:base64, filename:file.name } let res=await postRequest('/upload2',Qs.stringify(data),{headers:{'Content-Type':'application/x-www-form-urlencoded'}}) uploadImg.src=res.path; } function postRequest(url,data,config={}){ return axios.post(`http://127.0.0.1:8080${url}`,data,config).then(res=>res.data) } function readBase64(file){ return new Promise((resolve,reject)=>{ let fr=new FileReader() fr.readAsDataURL(file) fr.onload=function (ev){ resolve(ev.target.result) } }) } script> body> html> 

base64

封装:tree 图片懒加载 modalPlugin 文件上传插件……

文件上传:切片上传 断点续传 文件秒传

多文件

其实和单文件类似

上传进度:

axios: onUploadProgress:function(){}

原生js:onUpload

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件-多个文件title>
    <style>
        .thumbnail-box{
            width: 100px;
            height: 100px;
            position: relative;
            float: left;
        }
        .thumbnail-box img{width: 100%}
        .thumbnail-box .progress{
            position: absolute;
            bottom: 0;
            left: 0;
            height: 20px;
            width: 0;
            background: dodgerblue;
            transition: width .3s;
        }
        .thumbnail-box .mask{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.5);
        }
        .upload-draggable{
            width: 300px;
            height: 300px;
            line-height: 300px;
            background: darkgrey;
            font-size: 60px;
            display: block;
            vertical-align: middle;
            text-align: center;
        }
    style>
head>
<body>
<input type="file" id="uploadFile" accept="image/*"  multiple>
<div class="thumbnail">div> <img src="" alt="" width="100" id="uploadImg"> <div class="upload-draggable" contenteditable="true">+div> <script src="./js/axios.min.js">script> <script src="./js/qs.min.js">script> <script> uploadFile.onchange=async function (){ let files=this.files; if(!files.length) return; /** * 缩略图:通过fileReader去读取图片,得到base64编码 */ files=Array.from(files) let base64s=await Promise.all(files.map((file)=>readBase64(file))) let thumbHtml=base64s.reduce((html,base64,index)=>{ files[index].base64=base64 html+=`<div class="thumbnail-box"> <img src="${base64}" alt="" width="100%"> <div class="progress">div> <div class="mask">div> div>` return html; },'') let thumbContainer=document.querySelector('.thumbnail') thumbContainer.innerHTML=thumbHtml let thumbBox=document.querySelectorAll('.thumbnail-box') // 调接口 files.forEach(async (file,index)=>{ console.log(file); let data={ chunk:encodeURIComponent(file.base64), filename:file.name } let thumb=thumbBox[index] let progress=thumb.querySelector('.progress') let mask=thumb.querySelector('.mask') let config={ headers:{ 'Content-Type':'application/x-www-form-urlencoded' }, onUploadProgress:async function (ev){ let prog=Math.ceil(ev.loaded/ev.total*100); // 好像只进来了1次。。。 console.log('prog',prog,ev); progress.style.width=prog+'%' } } console.log(data); let res=await postRequest('/upload2',Qs.stringify(data),config) if(res.code===0){ await delay(1000) progress.style.display='none' mask.style.display='none' } }) } /** * 拖拽上传 * @param seconds * @returns {Promise<unknown>} */ let uploadDraggable=document.querySelector('.upload-draggable') console.log('uploadDraggable',uploadDraggable); uploadDraggable.ondrop=function (ev){ ev.preventDefault() let file=ev.dataTransfer.files; // ev.dataTransfer直接打印竟然没有,但是实际file是有的。。。无语 console.log('ondrop',ev.dataTransfer,file); } function delay(seconds=500){ return new Promise(resolve=>{ setTimeout(()=>resolve(),seconds) }) } function postRequest(url,data,config={}){ return axios.post(`http://127.0.0.1:8080${url}`,data,config).then(res=>res.data) } function readBase64(file){ return new Promise((resolve,reject)=>{ let fr=new FileReader() fr.readAsDataURL(file) fr.onload=function (ev){ resolve(ev.target.result) } }) } script> body> html> 

大文件上传

背景:文件比较大,直接传给服务器,导致传输时间过长过程中很容易出现问题;传失败还要重新传还要花这么多时间

思路

实现思路&逻辑:把文件切割成几个切片,不是一次性传给服务器,是一部分一部分传。服务器:可能会新建一个目录,把切片放到这个文件夹下。所有切片传完了,再向服务器发一个请求,服务器把所有把切片统一合并成一起,最后返回合成的文件。

断点续传:一共10个切片,只成功了3个,重新上传时服务器会提供一个接口当前已经上传了哪些切片,告诉我成功的切片。只把剩下7个传给服务器。(即使不提供接口服务器发现切片已经存在了它会立即返回一个成功,再或者就是客户端拉取一下哪些切片已经传了把没传的再传)。主题思路就是传过的就不再传了

根据文件内容生成hash值

async/await使用try-catch包起来

裁切方式:「固定大小」&「固定数量」

先以固定大小,若裁切的数量太大了超过了最大数量,就改成固定数量

用JavaScript实现文件的上传与下载_js文件上传fileupload_忧郁的蛋~的博客-CSDN博客

代码流程

获取已经上传的切片 /upload_already 

裁切大文件,一片一片上传 /upload_chunk。有一个切片传失败了我就停止上传,我就不再传了

都成功,调合并切片的接口 /upload_merge

GitHub - yaogengzhu/uploadFile: 文件上传、form-data方式、base64方式、文件上传进度条管控、多个文件上传、大文件上传(切片上传、断点续传)

GitHub - chinbor/bfu: About how to upload files, especially large files

涉及到的接口

获取已经上传的切片

https://www.cnblogs.com/zhuxianguo/p/11445952.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值