前端上传文件的几种方法

前端上传文件的几种方法,第1张

第一种:经典的form和input上传

设置form的aciton为后端页面,enctype="multipart/form-data",type=‘post’

<form action=';

使用input选择文件,设置好其他input的值,点击提交,将文件数据及签名等认证信息发送到form设置的action对应的页面,浏览器也会跳转到该页面。触发form表单提交数据的方式有2种,一种是在页面上点击button按钮或<input

type='submit'>按钮触发,第二种是在js中执行formsubmit()方法。

优点:使用简单方便,兼容性好,基本所有浏览器都支持。

缺点:1 提交数据后页面会跳转(下面会讲如何禁止页面跳转)。

2因为是浏览器发起的请求,不是一个ajax,所以前端无法知道什么时候上传结束。

3 form表单里发送除文件外的数据,一般是新建一个type=hidden的input,value=‘需要传的数据’,每发送一个数据就需要一个input,一旦多了就会使得dom看起来比较冗余。

小技巧:

form表单提交数据后会自动跳转到action指定的页面,为了禁止页面跳转,可以在页面中新建一个空的ifame,比如name='upload',然后设置form的target="Uploader",form有一个target的属性,规定在何处打开action,这样form提交数据后就会仍停留在当前页。代码如下:

<form action=';

这样写的另一个好处是,可以知道什么时候上传完成并接收到后端的回调结果。比如上面这个例子,文件数据发送到了

'uploadFilephp',假设该页面处理完数据后返回了一个地址,该地址会被写入到之前的iframe中。所以在ifame的onload函数触发时,也就是上传完成后,可以在iframe中读取到后端返回的数据。

var  iframe = documentgetElementById('upload1');

iframeonload = function () {  

                    var doc = windowframes['uploader1']document;                    var pre = docgetElementsByTagName('pre');                    var obj = JSONparse(pre[0]innerHTML);

                }

使用这种方法时需要注意,iframe有跨域限制,创建出来的iframe的地址如果和当前页面地址不同源,会报错。这种情况下,建议大家在iframe的onload函数中,再次向后端请求一个接口获取文件地址,而不是直接去iframe里读取。或者返回这样的数据。

<script type="text/javascript">windowtopwindow[callback](data)</script>

callback是和前端约定好的名字,上传完成后触发该函数并返回后端数据。

第二种:使用formData上传。

用js构造form表单的数据,简单高效,但最低只兼容IE10,所以需要兼容IE9的童鞋们就略过这个方法吧。

html:

<input type='file'>

js:

var formData = new FormData();

formDataappend("userid", userid);

formDataappend("signature", signature);

formDataappend("file", file); //file是blob数据//再用ajax发送formData到服务器即可,

注意一定要是post方式上传

说明:第一种方法提到了创建多个type=‘hidden’的input来发送签名数据,这儿可以用formDataappend方法来代替该 *** 作,避免了dom中有多个input的情况出现。最后将file数据也append到formData发送到服务器即可完成上传。

优点:由于这种方式是ajax上传,可以准确知道什么时候上传完成,也可以方便地接收到回调数据。

缺点:兼容性差

第三种:使用fileReader读取文件数据进行上传。

HTML5的新api,兼容性也不是特别好,只兼容到了IE10。

var fr = new FileReader();

                frreadAsDataURL(file);

                fronload = function (event) {                    var data= eventtargetresult; //此处获得的data是base64格式的数据                    imgsrc = data;

                    ajax(url,{data} ,function(){})

                }

上面获得的data可以用来实现上传前的本地预览,也可以用来发送base64数据给后端然后返回该数据块对应的地址。

优点: 同第二种

缺点:一次性发送大量的base64数据会导致浏览器卡顿,服务器端接收这样的数据可能也会出现问题。

原理分析

提取 *** 作:复制=>粘贴=>上传

在这个 *** 作过程中,我们需要做的就是:监听粘贴事件=>获取剪贴板里的内容=>发请求上传

为方便理解下文,需要先明白几点:

我们只能上传网页图(在网页上右键,然后复制)和截图(截图工具截的,eg:qq截图),不能粘贴上传系统里的(从桌面上、硬盘里复制),他们是存在完全不同的地方的。 截图工具截的图与在网页点击右键复制的图是有些不同的,因此处理方式也不一样。 知悉paste event这个事件:当进行粘贴(右键paste/ctrl+v) *** 作时,该动作将触发名为'paste'的剪贴板事件,这个事件的触发是在剪贴板里的数据插入到目标元素之前。如果目标元素(光标所在位置)是可编辑的元素(eg:设置了contenteditable属性的div。textarea并不行。),粘贴动作将把剪贴板里的数据,以最合适的格式,插入到目标元素里;如果目标元素不可编辑,则不会插入数据,但依然触发paste event。数据在粘贴的过程中是只读的。此段是翻译于w3org_the-paste-action。 可惜的是,经过试验,发现chrome(当前最新版)、firefox(当前最新版)、ie11对paste事件的实现并不是完全按照w3c来的,各自也有区别(w3c的paste标准也因此只是草案阶段)。

test代码如下:

chrome:

<textarea ></textarea> <div contenteditable style="width: 100px;height: 100px; border:1px solid"> </div> <script> documentaddEventListener('paste', function (event) { consolelog(event) }) </script>

event有clipboardData属性,且clipboardData有item属性,clipboardDataitem中的元素(对象)有type和kind属性; 无论在哪进行粘贴,均可触发paste事件; 在div(未特殊声明时,本文div均指设置了contenteditable属性的div) 里粘贴截图,不显示。imgsrc为base64编码字符串; 在div里粘贴网页,直接显示,imgsrc为地址。

firefox:

event有clipboardData属性,clipboardData没有item属性; 只有在textarea里或者可编辑的div(里才粘贴才触发paste事件; 在div里粘贴截图,直接显示,imgsrc为base64编码字符串; 在div里粘贴网页,表现同chrome。

ie11:(不截图了,可自行试验,其他浏览器同理<( ̄▽ ̄)/,因为懒)

event没有clipboardData属性; 只在可编辑的div中粘贴才触发paste事件; 在div里粘贴截图,直接显示,imgsrc为base64编码字符串; 在div里粘贴网页,表现同chrome。

监听了paste事件,也知道了表现形式,接下来就是如何获取数据了:

chrome有特定的方法,利用clipboardDataitems、getAsFile()、new FileReader()等api可以在paste回调函数里获取到剪贴板里的base64编码字符串(无论是截图粘贴的还是网页复制粘贴的),ie11,firefox没有这样的api,不过依然有办法可以获取,因为数据已经表现在img的src里了,对于截图粘贴的,直接取img的src属性值(base64),对于网页粘贴的,则把地址传给后台,然后根据地址down下来,存在自己的服务器,最后把新地址返回来交给前端展示就ok了。为了保持一致性便于管理,统一将所有情况(截图、网页)中的img的src属性替换为自己存储的地址。因此可以得到以下核心代码(注释很全哦~~):

html展示:

<head> <meta charset="UTF-8"> <title>Document</title> <style> body { display: -webkit-flex; display: flex; -webkit-justify-content: center; justify-content: center; } #tar_box { width: 500px; height: 500px; border: 1px solid red; } </style>

前端js处理逻辑:

documentaddEventListener('paste', function (event) { consolelog(event) var isChrome = false; if ( eventclipboardData || eventoriginalEvent ) { //not for ie11 某些chrome版本使用的是eventoriginalEvent var clipboardData = (eventclipboardData || eventoriginalEventclipboardData); if ( clipboardDataitems ) { // for chrome var items = clipboardDataitems, len = itemslength, blob = null; isChrome = true; //itemslength比较有意思,初步判断是根据mime类型来的,即有几种mime类型,长度就是几(待验证) //如果粘贴纯文本,那么len=1,如果粘贴网页,len=2, items[0]type = 'text/plain', items[1]type = 'image/' //如果使用截图工具粘贴,len=1, items[0]type = 'image/png' //如果粘贴纯文本+HTML,len=2, items[0]type = 'text/plain', items[1]type = 'text/html' // consolelog('len:' + len); // consolelog(items[0]); // consolelog(items[1]); // consolelog( 'items[0] kind:', items[0]kind ); // consolelog( 'items[0] MIME type:', items[0]type ); // consolelog( 'items[1] kind:', items[1]kind ); // consolelog( 'items[1] MIME type:', items[1]type ); //阻止默认行为即不让剪贴板内容在div中显示出来 eventpreventDefault(); //在items里找粘贴的image,据上面分析,需要循环 for (var i = 0; i < len; i++) { if (items[i]typeindexOf("image") !== -1) { // consolelog(items[i]); // consolelog( typeof (items[i])); //getAsFile() 此方法只是living standard firefox ie11 并不支持 blob = items[i]getAsFile(); } } if ( blob !== null ) { var reader = new FileReader(); readeronload = function (event) { // eventtargetresult 即为的Base64编码字符串 var base64_str = eventtargetresult //可以在这里写上传逻辑 直接将base64编码的字符串上传(可以尝试传入blob对象,看看后台程序能否解析) uploadImgFromPaste(base64_str, 'paste', isChrome); } readerreadAsDataURL(blob); } } else { //for firefox setTimeout(function () { //设置setTimeout的原因是为了保证先插入到div里,然后去获取值 var imgList = documentquerySelectorAll('#tar_box img'), len = imgListlength, src_str = '', i; for ( i = 0; i < len; i ++ ) { if ( imgList[i]className !== 'my_img' ) { //如果是截图那么src_str就是base64 如果是复制的其他网页那么src_str就是此在别人服务器的地址 src_str = imgList[i]src; } } uploadImgFromPaste(src_str, 'paste', isChrome); }, 1); } } else { //for ie11 setTimeout(function () { var imgList = documentquerySelectorAll('#tar_box img'), len = imgListlength, src_str = '', i; for ( i = 0; i < len; i ++ ) { if ( imgList[i]className !== 'my_img' ) { src_str = imgList[i]src; } } uploadImgFromPaste(src_str, 'paste', isChrome); }, 1); } }) function uploadImgFromPaste (file, type, isChrome) { var formData = new FormData(); formDataappend('image', file); formDataappend('submission-type', type); var xhr = new XML>

前端JS

var reader = new FileReader();

readeronload = function (e) {

//base64数据

var imgBase64Data = etargetresult;

var pos = imgBase64DataindexOf("4")+2;

imgBase64Data = imgBase64Datasubstring(pos, imgBase64Datalength - pos);//去掉Base64:开头的标识字符

$ajax({

type: "POST",

url: ">

已知路径,将该转换为base64数据流,怎么写啊

我现在是这样写的,结果不对啊

var file = p;//p是路径

if (file) {

var reader = new FileReader();

readeronload = function() {

var base64 = readerresultsplit(',')[1];

var dataUrl = 'data:imag

以上就是关于前端上传文件的几种方法全部的内容,包括:前端上传文件的几种方法、js怎么实现将截图,或者复制的图片用ctrl+v、前端将图片转换为base64位,使用ajax传递到后台,但是图片经过base64转换成字符串后非常长,无法使用ajax等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9661186.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存