1. 程式人生 > >檔案上傳常見問題整理

檔案上傳常見問題整理

檔案上傳:<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 為上傳檔案的最後修改時間

通過上面的幾個物件,我們能夠控制使用者上傳的檔案大小和檔案型別,以便減輕伺服器再次檢測時的壓力,並提升安全係數

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,TextgetData(sFormat)     從dataTransfer或者clipboardData中獲取值     sFormat:URL,TextclearData([sFormat])     通過dataTransfer或者clipboardData中刪除某種格式的資料     sFormat:Text,URL,File,HTML,Image

<!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就可以被用來追蹤進度。

<!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檔案內容預覽(需對<>&'"|等符號進行過濾否則會中斷讀取):

<!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指定區域文字內容:

<!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。

6、檔案讀取進度 
<!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