最专业的八方代购网站源码!

资讯热点
前端本地文件操作和上传

发布时间:2023-11-11 分类: 行业资讯

前端不能像本机APP那样直接操作本地文件。否则,打开网页可能会盗取用户计算机上的文件,因此需要由用户触发。用户可以通过以下三种方式触发操作:

通过输入类型=”文件”

选择本地文件

通过拖放拖放文件

复制并粘贴在编辑框中

第一种是最常用的方法,通常是自定义按钮,然后放在它上面,因为type=” file”输入不会改变风格。在以下代码中编写选择控件并将其放在以下格式中:

<形式>

< input type='file'id='file-input'name='fileContent'>

< /形式>

然后,您可以使用FormData获取整个表单的内容:

$('file-input')。on('change',function(){

Console.log(`文件名是$ {this.value}`);

设formData=new FormData(this.form);

formData.append('fileName',this.value);

CONSOLE.LOG(FORMDATA);

});

打印输入值和formData,如下所示:

您可以看到文件的路径是虚假路径,这意味着浏览器无法获取文件的实际存储位置。同时,FormData打印出一个空的Objet,但这并不意味着它的内容是空的,但它对前端开发人员来说是透明的。无法查看,修改和删除内容。只有追加才能添加字段。

FormData无法获取文件的内容,而FileReader可以读取整个文件的内容。用户选择文件后,input.files可以获取用户选择的文件,如下所示:

$('file-input')。on('change',function(){

让fileReader=new FileReader(),

fileType=this.files [0] .type;

fileReader.onload=function(){

如果(/^image/.test(fileType)) {

//在fileReader.result中读取结果

$(`< img src='$ {this.result}'>`)。appendTo('body');

}

}

//打印原始文件对象

CONSOLE.LOG(this.files [0]);

//base64 mode read

fileReader.readAsDataURL(this.files [0]);

});

像这样打印原始的File对象:

它是window.File的一个实例,它包含文件的修改时间,文件名,文件大小,文件的mime类型等。如果需要限制上载文件的大小,可以确定size属性是否为super。单位是字节。要确定它是否是图像文件,您可以从类型类型开始。通过判断文件名的后缀可能是不准确的,这种判断会更准确。上面的代码使用了常规判断。如果是图像,则将其分配给img的src并添加到dom。但实际上,这段代码有点问题,也就是说,并非所有的web图像都可以通过img标签显示。出来,通常是jpg/png/gif,所以你应该判断图像格式。如果你可以将判断改为:

/^图像/[JPEG | PNG | GIF] /测试(this.type)

然后实例化FileReader,调整其readAsDataURL并将其传递给File对象,监听其onload事件,并在其result属性中加载读取结果。它是一种base64格式,可以直接分配给img src。

除了可读为base64之外,还可以按以下格式读取FileReader:

//由base64读取,结果为base64,任何文件都可以转换为base64格式

fileReader.readAsDataURL(this.files [0]);

//作为二进制字符串读取,结果是二进制内容的utf-8形式,已被弃用

fileReader.readAsBinaryString(this.files [0]);

//读取原始二进制文件,结果可以直接转换为整数数组

fileReader.readAsArrayBuffer(this.files [0]);

另一个主要读作ArrayBuffer,它是原始二进制格式的结果。像这样打印出ArrayBuffer:

正如您所看到的,它对前端开发人员也是透明的。它无法直接读取内容,但可以通过ArrayBuffer.length获取长度。它也可以转换为整数数组,以了解文件的原始二进制内容:/p>

设buffer=this.result;

//依次读取每字节8位,将其放入整数数组

设view=new Uint8Array(buffer);

CONSOLE.LOG(视图);

如果您使用第二种拖动方法,您应该如何阅读文件?以下html(样式省略):

< div class='img-container'>

放下你的图像

</DIV>

这将在页面上显示一个框:

然后听听它的拖放事件:

$('。img-container')。on('dragover',function(event){

event.preventDefault();

})

.on('drop',function(event){

event.preventDefault();

//数据位于事件的dataTransfer对象

设file=event.originalEvent.dataTransfer.files [0];

//然后你可以使用FileReader来操作

fileReader.readAsDataURL(文件);

//或添加到FormData

设formData=new FormData();

formData.append('fileContent',file);

})

数据位于drop事件的event.dataTransfer.files中。获取File对象后,可以使用输入框执行相同的操作,即使用FileReader读取或创建空的formData,然后将其附加到formData。 。

第三种粘贴方式通常在编辑框中完成,例如将div的contenteditable设置为true:

< div contenteditable='true'>

您好,请在此处粘贴图片

</DIV>

粘贴的数据位于event.clipboardData.files:

$('editor')。on('paste',function(event){

设file=event.originalEvent.clipboardData.files [0];

});

但Safari的粘贴不会通过事件传递,而是直接在输入框中添加图片,如下所示:

它创建一个img标记并将img的src指向blob的本地数据。什么是blob,如何读取blob的内容?

Blob是类文件的存储格式,可以以几乎任何格式存储内容,例如json:

设data={hello:'world'};

设blob=new Blob([JSON.stringify(data)],

{type:'application/json'} ;;

为了获取本地blob数据,我们可以使用ajax发送本地请求:

$('editor')。on('paste',function(event){

//需要setTimeout 0和其他图像再次处理

setTimeout(()=> {

设img=$(this).find('img [src ^='blob']')[0];

CONSOLE.LOG(img.src);

//使用xhr

获取blob数据

设xhr=new XMLHttpRequest();

Xhr.open('GET',img.src);

//更改mime类型

xhr.responseType='blob';

Xhr.onload=function(){

//响应是一个Blob对象

CONSOLE.LOG(this.response);

};

Xhr.send();

},0);

});

上面的代码打印出这样的blob:

它可以获得它的大小和类型,但具体内容也是不可见的。它有一个切片方法,可用于剪切大文件。与File类似,您可以使用FileReader读取其内容:

函数readBlob(blobImg){

让fileReader=new FileReader();

fileReader.onload=function(){

CONSOLE.LOG(this.result);

}

fileReader.onerror=function(err){

CONSOLE.LOG(ERR);

}

fileReader.readAsDataURL(blobImg);

}

readBlob(this.response);

另外,你也可以使用window.URL来读取,这是一个新的API,经常与Service Worker一起使用,因为SW经常要解析url。以下代码:

函数readBlob(blobImg){

设urlCreator=window.URL || window.webkitURL;

//获取base64结果

设imageUrl=urlCreator.createObjectURL(this.response);

返回imageUrl;

}

readBlob(this.response);

关于src是使用blob链接,除了上面提到的img之外,另一个很常见的是视频标签,比如youtobe视频是使用blob:

这些数据不是直接本地的,而是由视频数据不断请求,然后通过blob容器媒体添加到视频中,它也是通过URL API创建的:

让mediaSource=new MediaSource();

Video.src=URL.createObjectURL(mediaSource);

让sourceBuffer=mediaSource.addSourceBuffer('video/mp4; codecs='avc1.42E01E,mp4a.40.2'');

sourceBuffer.appendBuffer(BUF);

我没有具体实践过,也不会讨论它。

上面,我们用三种方法获取文件的内容,最后得到:

FormData格式

FileReader读取的base64或ArrayBuffer二进制格式

如果它直接是FormData,那么就直接用ajax发布就行了,不需要做任何事情:

设form=document.querySelector('form'),

formData=new FormData(form),

formData.append('fileName','photo.png');

设xhr=new XMLHttpRequest();

//假设上传文件的界面叫做upload

Xhr.open('POST','/upload');

Xhr.send(FORMDATA);

如果使用jQuery,请将两个属性设置为false:

$就({

网址:'/upload',

输入:'POST',

数据: formData,

processData: false,//不处理数据

contentType: false //不设置内容类型

});

因为jQuery会自动转义内容,并根据数据自动设置请求mime类型,告诉jQuery直接用xhr.send发送它。

观察控制台发送的数据:

< form enctype='multipart/form-data'method='post'>

< input type='file'name='fileContent'>

< /形式>

如果xhr.send是FormData类型,它将自动设置enctype。如果您使用默认表单提交上载的文件,则必须在表单上设置此属性,因为上载文件只能使用此POST编码。常用的POST编码是application/x-www-form-urlencoded,与GET一样,使用&编码器。参数和参数之间的连接,例如:

键1=值&安培;键2=值

特殊字符正在逃避。此数据POST放在请求正文中,GET拼写在网址上。如果使用jq,jq将帮助你拼写和转义。

用于上传文件的multipart/form-data通过参数和参数与相同的字符串分开。使用以上内容:

&MDASH;&MDASH; WebKitFormBoundary72yvM25iSPYZ4a3F

这个字符通常变得更长,更随机,因为它保证字符串不会出现在正常内容中,因此内容的特殊字符不需要转义。

请求的contentType由浏览器设置为:

内容类型:

多部分/格式的数据;边界=&MDASH; -WebKitFormBoundary72yvM25iSPYZ4a3F

后端服务知道如何通过此解析这样的数据。 (通常使用的框架是处理的,特定的接口不需要关心它应该如何解决)

如果读取的结果是ArrayBuffer,它也可以由xhr.send直接发送,但通常我们不会直接发送文件的内容,而是使用等于文件内容的字段名称。如果您将其作为ArrayBuffer读取然后上传它,效果不是很大。最好使用formData直接添加File对象的内容,因为上述三种方法都可以获取File对象。如果从ArrayBuffer开始,可以将其转换为blob,然后将其附加到FormData。

更常用的应该是base64,因为前端经常需要处理图像,在读取它为base64之后,它可以被绘制到画布中,然后你可以做一些处理,比如压缩,裁剪,旋转和等等。最后,使用canvas导出base64格式的图像,如何上传base64格式?

第一种是拼写由表单上传的multipart/form-data的格式,然后用xhr.sendAsBinary发送出来,如下所示:

设base64Data=base64Data.replace(/^ data: image/[^;] +; base64,/,'');

设border='---------- boundaryasoifvlkasldvavoadv';

xhr.sendAsBinary([

//name=data

边界,

'内容 - 处置:表单数据;命名=“数据”; filename=''+ fileName +''',

'Content-Type:'+'image /'+ fileType,'',

Atob(base64Data),边界,

//名称=IMAGETYPE

边界,

'内容 - 处置:表单数据; name='imageType'','',

的fileType,

边界+' - '

]。加入('“));

上面的代码使用了window.atob的api,它将base64恢复为原始内容的字符串表示形式,如下所示:

Btoa将内容转换为base64编码,而atob则恢复base64。在调优atob之前,您需要删除表示不属于base64内容的内容格式的字符串,即上述代码第一行的替换处理。

这与使用formData类似,但由于不推荐使用sendAsBinary,因此新代码不建议使用此方法。那我们该怎么办?

您可以将base64转换为blob,然后附加到formData。以下函数(从b64到blob)可以将base64转换为blob:

函数b64toBlob(b64Data,contentType,sliceSize){

contentType=contentType || “”;

sliceSize=sliceSize || 512;

Var byteCharacters=atob(b64Data);

Var byteArrays=[];

For(var offset=0; offset< byteCharacters.length; offset +=sliceSize){

Var slice=byteCharacters.slice(offset,offset + sliceSize);

Var byteNumbers=new Array(slice.length);

对于(var i=0; i< slice.length; i ++){

byteNumbers [i]=slice.charCodeAt(i);

}

Var byteArray=new Uint8Array(byteNumbers);

byteArrays.push(字节阵列);

}

Var blob=new Blob(byteArrays,{type: contentType});

返回blob;

}

然后你可以追加到formData:

设blob=b64toBlob(b64Data,'image/png'),

formData=new FormData();

formData.append('fileContent',blob);

这样您就不必自己拼写多部分/表单数据格式数据。

用于处理和上传上述文件的API可与IE10 +兼容。如果我想与旧浏览器兼容,我该怎么办?

你可以使用iframe,原理是默认表单表单提交会刷新页面,或者跳转到目标指定的url,但如果ifrmae目标指向iframe,那么刷新就是iframe,返回结果也会在ifame中显示,然后获取此ifrmae的内容以获取上传界面返回的结果。

以下代码:

设iframe=document.createElement('iframe');

Iframe.display='none';

iframe.name='form-iframe';

document.body.appendChild(IFRAME);

//更改表单的目标

Form.target='form-iframe';

iframe.onload=function(){

//获取iframe的内容,即服务返回的数据

设responseText=this.contentDocument.body.textContent

|| this.contentWindow.document.body.textContent;

};

Form.submit();

Form.submit将触发表单提交。当请求完成(成功或失败)时,将触发iframe的onload事件,然后在onload事件中检索返回的数据。如果请求失败,则iframe的内容将为空。该判决请求已成功。

没有办法使用iframe获取上传进度,使用xhr来获取当前上传的进度,这是在XMLHttpRequest 2.0中引入的:

Xhr.upload.onprogress=function(event){

If(event.lengthComputable){

//当前上传进度的百分比

duringCallback((event.loaded/event.total)* 100);

}

};

这将成为一个真正的加载进度条。

本文讨论了交互式阅读的三种方式。您可以通过输入控件获取input.files中的File对象。拖放位于drop事件的event.dataTransfer.files中,粘贴事件将粘贴到事件中。在clipboardData.files中,Safari狂热的是将src插入编辑器中的本地img标记。您可以通过发送请求加载本地blob数据,然后通过FileReader读取它,或直接附加到formData。获取的File对象可以直接添加到FormData。如果需要读取base64格式进行处理,可以将处理后的base64转换为blob数据并将其附加到formData。对于旧版浏览器,您可以使用iframe来解决提交页面或刷新页面的问题。

总之,本地文件的前端处理和上传应该几乎相同,但是应该有很多未提及的细节,读者可以按照本文所列的方向练习。如果有其他上传方法,请告诉我。

« 这一次,从“小事”开始,豆瓣的修改是否正确 | 响应临时设计要求,使用简易地图网络获得3分钟 »