文件上传常见问题整理
文件上传:<input type="file" /> (IE9及以下不支持下面这些功能,其它浏览器最新版本均已支持。)
1、允许上传文件数量
允许选择多个文件:<input type="file" multiple>
只允许上传一个文件:<input type="file" single>
2、上传指定的文件格式
<input type="file" accept="image/gif,image/png" />
这里的上传格式仅指打开上传弹窗选择文件时默认的文件格式,可手动修改成其它文件格式。
如果不限制上传图片的格式可写成:accept="image/*"
其它格式参考如下:
*.3gpp audio/3gpp, video/3gpp 3GPP Audio/Video *.ac3 audio/ac3 AC3 Audio *.asf allpication/vnd.ms-asf Advanced Streaming Format *.au audio/basic AU Audio *.css text/css Cascading Style Sheets *.csv text/csv Comma Separated Values *.doc application/msword MS Word Document *.dot application/msword MS Word Template *.dtd application/xml-dtd Document Type Definition *.dwg image/vnd.dwg AutoCAD Drawing Database *.dxf image/vnd.dxf AutoCAD Drawing Interchange Format *.gif image/gif Graphic Interchange Format *.htm text/html HyperText Markup Language *.html text/html HyperText Markup Language *.jp2 image/jp2 JPEG-2000 *.jpe image/jpeg JPEG *.jpeg image/jpeg JPEG *.jpg image/jpeg JPEG *.js text/javascript, application/javascript JavaScript *.json application/json JavaScript Object Notation *.mp2 audio/mpeg, video/mpeg MPEG Audio/Video Stream, Layer II *.mp3 audio/mpeg MPEG Audio Stream, Layer III *.mp4 audio/mp4, video/mp4 MPEG-4 Audio/Video *.mpeg video/mpeg MPEG Video Stream, Layer II *.mpg video/mpeg MPEG Video Stream, Layer II *.mpp application/vnd.ms-project MS Project Project *.ogg application/ogg, audio/ogg Ogg Vorbis *.pdf application/pdf Portable Document Format *.png image/png Portable Network Graphics *.pot application/vnd.ms-powerpoint MS PowerPoint Template *.pps application/vnd.ms-powerpoint MS PowerPoint Slideshow *.ppt application/vnd.ms-powerpoint MS PowerPoint Presentation *.rtf application/rtf, text/rtf Rich Text Format *.svf image/vnd.svf Simple Vector Format *.tif image/tiff Tagged Image Format File *.tiff image/tiff Tagged Image Format File *.txt text/plain Plain Text *.wdb application/vnd.ms-works MS Works Database *.wps application/vnd.ms-works Works Text Document *.xhtml application/xhtml+xml Extensible HyperText Markup Language *.xlc application/vnd.ms-excel MS Excel Chart *.xlm application/vnd.ms-excel MS Excel Macro *.xls application/vnd.ms-excel MS Excel Spreadsheet *.xlt application/vnd.ms-excel MS Excel Template *.xlw application/vnd.ms-excel MS Excel Workspace *.xml text/xml, application/xml Extensible Markup Language *.zip aplication/zip Compressed Archive
3、FileList上传文件数组
FileList对象都是一组文件对象的集合,而文件对象则拥有下列的属性:
name – 文件名(不包含路径)
type – 文件的MIME类型(小写)
size – 文件的尺寸(单位为字节)
lastModifiedDate 为上传文件的最后修改时间
通过上面的几个对象,我们能够控制用户上传的文件大小和文件类型,以便减轻服务器再次检测时的压力,并提升安全系数
1 2 3 4 5 6 | var a=document.getElementById( "file" ); a.onchange= function (e){ e=e || window.event; var b=e.target.files; alert(b[0].name); } |
4、拖动上传
dataTransfer 对象
dropEffect[=sCursorStyle]
设置或获取拖拽操作的类型和要显示的光标类型
copy:复制样式被显示
link:链接样式被显示
move:移动样式被显示
none:默认,没有鼠标样式被定义
effectAllowed[=sEffect]
设置或获取数据传送操作可应用与该对象的源元素
copy 选项被复制
link 选项被dataTransfer作为link方式保存
move 当放置时,对象被移动至目标对象
copylink 选项是被复制还是被作为link方式保存关键在于目标对象
linkmove 选项是被作为link方式保存还是被移动关键在于目标对象
all 所有效果都被支持
none 不支持任何效果
uninitialized 默认不能通过这个属性传递任何值
setData(sFormat,sData) 将指定格式的数据赋值给dataTransfer或者clipboardData sFormat:URL,Text
getData(sFormat) 从dataTransfer或者clipboardData中获取值 sFormat:URL,Text
clearData([sFormat]) 通过dataTransfer或者clipboardData中删除某种格式的数据 sFormat:Text,URL,File,HTML,Image
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <!DOCTYPE HTML> <html> <head> <meta charset= "utf-8" > <title></title> <style type= "text/css" > #DropZone{border:1px solid #CCC;height:50px;} </style> </head> <body> <input type= "file" multiple accept= "image/gif,image/png" id= "file" > <div id= "DropZone" ></div> <div id= "Lists" ></div> <script> var aa=document.getElementById( "file" ); aa.onchange= function (){ fileDrop(); } function fileDrop(e) { e = e || window.event; e.stopPropagation(); // 阻止冒泡 e.preventDefault(); //阻止默认行为 var files = e.dataTransfer.files; //FileList var output = []; for ( var i = 0, f; f = files[i]; i++) { output.push( '<li><strong>' + f.name + '</strong>(' + f.type + ') - ' + f.size + ' bytes</li>' ); } document.getElementById( 'Lists' ).innerHTML = '<ul>' + output.join( '' ) + '</ul>' ; }; function dragOver(e) { e = e || window.event; e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = 'copy' ; //指定拖放视觉效果 }; var d = document.getElementById( 'DropZone' ); try { d.addEventListener( 'dragover' , dragOver, false ); d.addEventListener( 'drop' , fileDrop, false ) } catch (ex) { document.write( 'something must be wrong!' ); } </script> </body> </html> |
5、FileReader文件预览,读取文件数据(同时可读取图片文件宽高)
FileReader包含四种异步读取文件的方式:
FileReader.readAsBinaryString(Blob|File) - result属性包含的是file/blob的二进制字符串形式的数据。每个字节由一个0-255的整数表示。
FileReader.readAsText(Blob|File, opt_encoding) - result属性包含的是以文本方式表示的file/blob数据。默认情况下,字符串以'UTF-8'编码方式解码。使用opt_encoding参数可以指定一个不同的格式。
FileReader.readAsDataURL(Blob|File) - result属性包含的是以data URL编码的file/blob数据。
FileReader.readAsArrayBuffer(Blob|File) - result属性包含的是以ArrayBuffer对象表示的file/blob数据。
一旦这些read方法被调用,onloadstart, onprogress, onload, onabort, onerror, onloadend就可以被用来追踪进度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | <!DOCTYPE HTML> <html> <head> <meta charset= "utf-8" > <title></title> <style type= "text/css" > body{margin:0;padding:0;} img{vertical-align:bottom;} </style> </head> <body> <input type= "file" multiple accept= "image/gif,image/png,,image/jpeg" id= "Files" > <div id= "Preview" ></div> <ul id= "Errors" ></ul> <script> function fileSelect(e) { e = e || window.event; var files = e.target.files; //FileList Objects var ireg = /image\/.*/i, p = document.getElementById( 'Preview' ); var ul = document.getElementById( 'Errors' ); for ( var i = 0, f; f = files[i]; i++) { if (!f.type.match(ireg)) { //设置错误信息 var li = document.createElement( 'li' ); li.innerHTML = '<li>' + f.name + '不是图片文件.</li>' ; ul.appendChild(li); continue ; } var reader = new FileReader(); reader.onload = ( function (file) { return function (e) { var span = document.createElement( 'span' ); var img = new Image; img.alt=file.name; img.onload = function () { console.log(img.height); // image is loaded; sizes are available }; img.src= this .result; span.innerHTML = '<img class="thumb" src="' + this .result + '" alt="' + file.name + '" />' ; p.insertBefore(span, null ); }; })(f); //读取文件内容 reader.readAsDataURL(f); } } if (window.File && window.FileList && window.FileReader && window.Blob) { document.getElementById( 'Files' ).addEventListener( 'change' , fileSelect, false ); } else { document.write( '您的浏览器不支持File Api' ); } </script> </body> </html> |
上传txt文件内容预览(需对<>&'"|等符号进行过滤否则会中断读取):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <!DOCTYPE HTML> <html> <head> <meta charset= "utf-8" > <title></title> <style type= "text/css" > body{margin:0;padding:0;} img{vertical-align:bottom;} </style> </head> <body> <input type= "file" multiple id= "Files" > <div id= "Preview" ></div> <ul id= "Errors" ></ul> <script> function encodeHTML(source) { //return source; return source .replace(/&/g, '&' ) .replace(/</g, '<' ) .replace(/>/g, '>' ) .replace(/\ "/g, '" '); }; function fileSelect(e) { e = e || window.event; var files = e.target.files; //FileList Objects var ireg = /text\/.*/i, p = document.getElementById( 'Preview' ); var ul = document.getElementById( 'Errors' ); for ( var i = 0, f; f = files[i]; i++) { console.log(f.type); if (!f.type.match(ireg)) { //设置错误信息 var li = document.createElement( 'li' ); li.innerHTML = '<li>' + f.name + '不是文本文件.</li>' ; ul.appendChild(li); continue ; } var reader = new FileReader(); reader.onload = ( function (file) { return function (e) { var div = document.createElement( 'div' ); div.className = "text" div.innerHTML = encodeHTML( this .result); p.insertBefore(div, null ); }; })(f); //读取文件内容 reader.readAsText(f); } } if (window.File && window.FileList && window.FileReader && window.Blob) { document.getElementById( 'Files' ).addEventListener( 'change' , fileSelect, false ); } else { document.write( '您的浏览器不支持File Api' ); } </script> </body> </html> |
读取上传txt指定区域文本内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | <!DOCTYPE HTML> <html> <head> <meta charset= "utf-8" > <title></title> <style type= "text/css" > body{margin:0;padding:0;} img{vertical-align:bottom;} </style> </head> <body> <input type= "file" multiple id= "Files" > <button type= "button" id= "buttons" data-start= "0" data-end= "3" >确定</button> <div id= "range" ></div> <div id= "content" ></div> <script> function readBlob(start, end) { var files = document.getElementById( 'Files' ).files; if (!files.length) { alert( '请选择文件' ); return false ; } var file = files[0], start = parseInt(start, 10) || 0, end = parseInt(end, 10) || (file.size - 1); var r = document.getElementById( 'range' ), c = document.getElementById( 'content' ); var reader = new FileReader(); reader.onloadend = function (e) { if ( this .readyState == FileReader.DONE) { c.textContent = this .result; r.textContent = "Read bytes: " + (start + 1) + " - " + (end + 1) + " of " + file.size + " bytes" ; } }; var blob; blob = file.slice(start, end + 1, 'text/plain;charset=UTF-8' ); reader.readAsBinaryString(blob); }; try { document.getElementById( 'buttons' ).addEventListener( 'click' , function (e) { if (e.target.tagName.toLowerCase() == 'button' ) { var start = e.target.getAttribute( 'data-start' ), end = e.target.getAttribute( 'data-end' ); readBlob(start, end); } }); } catch (ex) { alert( 'something error happens!' ) } </script> </body> </html> |
File接口提供了slice方法支持把文件切成不同的片段,第一个参数是起始的字节数,第二个参数是结束的字节数,还有一个可选的内容类型字符串可以作为第三个参数。早期的chrome和firefox版本不支持file.slice 可使用file.webkitSlice和file.mozSlice替代,最新版本均支持file.slice。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | <!DOCTYPE HTML> <html> <head> <meta charset= "utf-8" > <title></title> </head> <body> <form> <fieldset> <legend>分度读取文件:</legend> <input type= "file" id= "File" /> <input type= "button" value= "中断" id= "Abort" /> <p> <label>读取进度:</label><progress id= "Progress" value= "0" max= "100" ></progress> </p> <p id= "Status" ></p> </fieldset> </form> <script> var h = { init: function () { var me = this ; document.getElementById( 'File' ).onchange = me.fileHandler; document.getElementById( 'Abort' ).onclick = me.abortHandler; me.status = document.getElementById( 'Status' ); me.progress = document.getElementById( 'Progress' ); me.percent = document.getElementById( 'Percent' ); me.loaded = 0; //每次读取1M me.step = 1024 * 1024; me.times = 0; }, fileHandler: function (e) { var me = h; var file = me.file = this .files[0]; var reader = me.reader = new FileReader(); // me.total = file.size; reader.onloadstart = me.onLoadStart; reader.onprogress = me.onProgress; reader.onabort = me.onAbort; reader.onerror = me.onerror; reader.onload = me.onLoad; reader.onloadend = me.onLoadEnd; //读取第一块 me.readBlob(file, 0); }, onLoadStart: function () { var me = h; }, onProgress: function (e) { var me = h; me.loaded += e.loaded; //更新进度条 me.progress.value = (me.loaded / me.total) * 100; }, onAbort: function () { var me = h; }, onError: function () { var me = h; }, onLoad: function () { var me = h; if (me.loaded < me.total) { me.readBlob(me.loaded); } else { me.loaded = me.total; } }, onLoadEnd: function () { var me = h; }, readBlob: function (start) { var me = h; var blob, file = me.file; me.times += 1; if (file.slice) { blob = file.slice(start, start + me.step + 1); } else if (file.mozSlice) { blob = file.mozSlice(start, start + me.step + 1); } me.reader.readAsText(blob); }, abortHandler: function () { var me = h; if (me.reader) { me.reader.abort(); } } }; h.init(); </script> </body> </html> |
本文代码以chrome测试为主。
参考资料:
http://blog.csdn.net/zhu1988renhui/article/details/7936498
http://blog.csdn.net/zhu1988renhui/article/details/7936525
http://dev.w3.org/2006/webapi/FileAPI/#dfn-filereader
http://www.html5rocks.com/zh/tutorials/file/dndfiles/
http://www.w3.org/TR/file-upload/
http://www.w3.org/TR/file-upload/#dfn-filereader
http://www.w3.org/TR/file-upload/#dfn-Blob
http://www.w3.org/TR/file-upload/#dfn-fileerror
http://www.w3.org/TR/progress-events/#Progress
http://www.zhangxinxu.com/wordpress/?p=1923
http://www.tfan.org/wp-content/slides/file.html#1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2017-11-14 Markdown调查
2016-11-14 弹性布局学习-介绍(一)