跳到主要內容
黯羽輕揚每天積累一點點

檔案拖放上傳

免費2015-07-06#HTML#JS#Solution#文件拖放上传.HTML5拖放#HTML5拖动#文件上传#无刷新上传#FormData

HTML5 支援檔案拖放上傳,拖放上傳直觀便捷,使用者體驗更好。本文介紹 FormData + Ajax 的實作方式,提供完整前後端(PHP)程式碼

##一.用 input 控件實作拖放上傳

<form action="http://localhost:82/drag&drop/fileUpload.php" method="POST" enctype="multipart/form-data">
    <input type="file" name="myfile" id="">
    <input type="submit" value="上傳檔案">
</form>

注意:必須設置 method="POST"enctype="multipart/form-data" 以及 type="file" name="myfile"三者缺少任何一個都會導致後端 PHP 無法收到數據

當然,把檔案拖放上去之後,點擊 submit 按鈕,然後瀏覽器顯示忙碌狀態,頁面就開始重新整理。用提交表單的方式無法避免上傳檔案時的頁面重新整理,後面介紹的方式可以實現無重新整理拖放上傳

(後端程式碼與 FormData + Ajax 方式相同,請看後文)

##二.用 FormData + Ajax 實作拖放上傳

<div id="dropArea3">檔案放置區域</div>
<script>
// 可拖放元素
var area3 = document.getElementById('dropArea3');
// 檔案放置區域
area3.ondragover = function(e) {
    e.preventDefault();
}
area3.ondrop = function(e) {
    e.preventDefault();
    var files = e.dataTransfer.files;
    if (files && files.length > 0) {
        // 輸出檔案資訊
        var str = '';
        for(var i = 0; i < files.length; i++) {
            var file = files[i];
            // 線上預覽圖片也需要先把圖片上傳到伺服器,因為無法獲取用戶端檔案 url
            // 上傳檔案直接 xhr 發送 file 物件即可
            var formData = new FormData();
            formData.append('myfile', file);
            // JQ 方式
            // $.ajax({
            //     type : 'POST',
            //     url: 'http://localhost:82/drag&drop/fileUpload.php',
            /* 必須設置下面兩個屬性,否則會導致$_FILES收不到數據 */
            //     processData: false,
            //     contentType: false,
            //     data: formData,
            //     success: function(res){
            //         console.log('success');
            //         console.log(res);
            //     },
            //     error: function(res) {
            //         console.log('error');
            //     }
            // });
            // 原生 JS 方式
            var xhr = new XMLHttpRequest();    
            xhr.open("POST", "http://localhost:82/drag&drop/fileUpload.php", true);
            /* 千萬不能設置,會導致$_FILES收不到數據 */
            // xhr.setRequestHeader('Content-Type', 'multipart/form-data');
            xhr.send(formData);
            xhr.onload = function(e) {
                if (this.status == 200) {
                    console.log(this.responseText);
                }
            };
            console.log(file);
        }
        console.log('receive a file');
    }
}
</script>

上面程式碼介紹了兩種方式:JQuery 和原生 JS。看程式碼可以發現,其實用原生 JS 更方便(要注意千萬不能設置 ContentType ),畢竟需要注意的這一點很容易誤打誤撞成功。而 JQuery 的實作方式則不好理解(必須設置 processData 和 contentType 為 false ,這怎麼可能想得到。。)。

所以,建議採用原生 JS 來實現這部分,至於相容性,支援拖放檔案的瀏覽器也應該早就支援標準 xhr 了

##三.後端處理

首先明確一點,雖然 Ajax 發送檔案用的是 POST 方法,但發送的畢竟是檔案(有一些額外的屬性),不是普通字串。所以 PHP 後端是用 $_FILES 陣列來接收的,而不是 $_POST 陣列

<?php
/* 從$_FILES中取,而不是$_POST */
$file = $_FILES['myfile'];
$fileName = $file['name'];
// echo $fileName;
$fileSize = $file['size'];
// echo $fileSize;
if ($fileName != "") {
    $rand = rand(100, 999);
    $pics = date("YmdHis") . $rand . $fileName;
    //上傳路徑
    $filePath = "files/". $pics;
    /* tmp_name是定死的,php出於伺服器安全性考慮,過濾檔案名稱 */
    if (move_uploaded_file($_FILES['myfile']["tmp_name"], $filePath)) {
        echo $filePath;
    }
}
?>

注意上面的多行註解內容,尤其是 move_uploaded_file 函式的參數,不知道的話是肯定寫不對的

###參考資料:

  • 前輩博文若干

評論

暫無評論,快來發表你的看法吧

提交評論