前端文件上傳-javascript-ajax

書寫是爲了更好的記憶。jquery

方案一:form表單上傳

該方案優勢是支持好,缺點刷新頁面。ajax

<form action="url"  method="post" enctype="multipart/form-data">
    <input type="file" name="file"><input type="submit" value="提交">
</form>

原理:enctype就是form上傳文件的重點。跨域

描述
application/x-www-form-urlencoded 默認。在發送前對全部字符進行編碼(將空格轉換爲 "+" 符號,特殊字符轉換爲 ASCII HEX 值)
multipart/form-data 不對字符編碼。當使用有文件上傳控件的表單時,該值是必需的
text/plain 將空格轉換爲 "+" 符號,但不編碼特殊字符

方案二:form表單上傳-優化方案一缺點

該方案的優勢也是支持好,缺點是不支持跨域。app

<form action="url"  method="post" enctype="multipart/form-data" target="iframe">
    <input type="file" name="file"><input type="submit" value="提交">
</form>

原理:經過target把響應指向一個iframe頁面,以後拿到返回數據。框架

描述
_blank 在新窗口/選項卡中打開
_self 默認, 在同一框架中打開
_parent 在父框架中打開。
_top 在整個窗口中打開
framename 在指定的 iframe 中打開

方案三:ajax上傳-優化方案二缺點

該方案的缺點兼容問題-caniuse,兼容有兩個方向一是低版本ie不支持CORS跨域,一個就是input新加的Files。優勢就是異步,進度條,判斷大小,處理,跨域。異步

var file = input.files[0];
var xhr = new XMLHttpRequest();
if (xhr.upload) {
    xhr.upload.addEventListener("progress", function(e) {
        console.log(file, e.loaded, e.total);
    }, false);
    // 文件上傳成功或是失敗
    xhr.onreadystatechange = function(e) {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                console.log('成功', xhr.responseText)
            } else {
                console.log('失敗')    
            }
        }
    }
    // 開始上傳
    xhr.open("POST", 'url', true);
    xhr.send(file);
}

方案四:ajax-formData上傳-多字段多文件;

該方案基本同上,只不過使用了FormData,缺點就是formData的兼容post

var formData = new FormData();
formData.append('file', input.files[0]);
xhr.send(formData);

其餘方案:

1. SWFupload Flash上傳
2. jquery.form.js 其餘插件上傳

需求一:拖拽上傳

使用drop事件,獲取e.dataTransfer優化

document.querySelector('body').addEventListener("drop", (e)=>{
    e.preventDefault();//不寫的話,就打開了
    console.log(e.dataTransfer.files[0])
});

需求二:截圖-粘貼-上傳

使用paste事件,獲取e.clipboardDataui

document.querySelector('body').addEventListener("paste", (e)=>{
    e.preventDefault();//不寫的話,就打開了
    console.log(e.clipboardData.files[0])
});

需求三:base64轉換上傳

場景發生在,一個和客戶端交互的狀況下,客戶端選擇的圖片以後返給我了一個base64,讓我上傳這個,並且接口那邊還不改,就要文件。代碼寫的比較囉嗦,其實也用不了這麼多東西,當時也是第一次接觸atobBlobArrayBuffer這些東西,就寫成這樣了。編碼

function(data){
    var _str = atob(data.base64Str)
    var _filePath = ((data.filePath.match(/.(jpg|jpeg|png|bmp)$/) || [])[1] || 'png').toLowerCase();
    var _filePathHash = {
        jpg:'image/jpeg',jpeg:'image/jpeg',png: 'image/png',bmp:'application/x-bmp',
    }
    var pre = '--------------------------1\r\nContent-Disposition: form-data; name="file"; filename="1.png"\r\nContent-Type: '+_filePathHash[_filePath]+'\r\n\r\n';
    var end = '\r\n--------------------------1--';
    var buffer = new ArrayBuffer(_str.length);
    var uint8 = new Uint8Array(buffer);
    for(var i in _str){
        uint8[i] = _str.charCodeAt(i);
    }
    var blob = new Blob([pre, uint8, end], {type: _filePathHash[_filePath]});
    var oReq = new XMLHttpRequest();
    oReq.open("POST", "url", true);
    oReq.setRequestHeader("Content-Type", "multipart/form-data; boundary=------------------------1")
    oReq.onreadystatechange=function(){if (oReq.readyState==4 && oReq.status==200){console.log(oReq.responseText); }
    oReq.send(blob);

需求四

上傳通常來講都是要寫樣式的,不能說光是默認的input樣式就ok,可是呢,樣式又不是那麼太好寫,咱們怎麼辦呢?

方案一

label標籤的for去觸發input的單擊,這樣不就行了嗎?input的樣式很差寫,那咱們把他藏起來,給label寫樣式。

方案二

input[type=file]左邊是一個input右邊是個按鈕,實際上是按鈕的樣式很差改,那麼咱們外面包裹一層overlfow:hidden,而後給input設置成一個極大,讓他全部不同的東西,都超出去,這樣就是在能改動的區域改動了

相關文章
相關標籤/搜索