HTML5拖拽檔案上傳

GGCoder發表於2020-12-31

上傳檔案

HTML5新增了檔案API,提供客戶端本地操作檔案的可能.

我們可以通過file表單或拖放操作選擇檔案,還可以通過JavaScript讀取檔案的名稱、大小、型別、和修改時間.

file型別的input表單新增了files屬性,儲存我們上傳檔案的資訊,如果要實現多檔案上傳,可以設定input的multiple屬性.

可以使用accept屬性規定檔案上傳的MIME型別 例如’image/jpeg’

<form action="#">
        <div class="form-group">
            <label for="input_1">請選擇檔案</label>
            <input id="input_1" class="form-control" name="input_1" type="file">
        </div>
        <div class="form-group">
            <button id="btn_1" class="btn btn-default" type="button">讀取檔案資訊</button>
        </div>
</form>
<pre id="result"></pre>
</div>
<script>
var btn = document.querySelector('#btn_1');
var input = document.querySelector('#input_1');
btn.addEventListener('click', function() {
    // 獲取檔案域中選擇的檔案
    // var file = input.files[0];
    var file = input.files.item(0);
    if (file) {
        result.innerHTML =
            '檔名:' + file.name + '\n檔案最近修改時間:' + file.lastModifiedDate+ '\n檔案型別:' + file.type + '\n檔案大小:' + file.size + '位元組'
    } else {
        result.innerHTML = '沒有選擇任何檔案';
    }
});
</script>

頁面拖拽操作

對於被拖拽的元素,HTML5增加了三個事件用於監聽拖拽的過程

  • dragstart 拖拽開始
  • drag 正在拖拽
  • dragend 拖拽結束
<body>
    <div id="one" style="width: 300px;height: 300px;border: 1px solid red"></div>
    <div id="two" style="width: 100px;height: 100px;border: 1px solid blue" draggable="true"></div>
</body>
<script type="text/javascript">
    two.ondragstart = function(e){
        // e.preventDefault();
        console.log(e);
        e.dataTransfer.setData("Text",e.target.id);
        console.log(e.dataTransfer.getData("Text",e.target.id));
        one.innerHTML = '開始'
    }
    two.ondrag = function(e){
        one.innerHTML += '拖動中'
    }
    two.ondragend = function(e){
        one.innerHTML = '結束'
    }
</script>

想要拖拽元素,必須設定draggable屬性

頁面預設的動作是拖拽後回到原位

在拖動階段,我們可以儲存被拖動元素的屬性或者狀態到事件物件的dataTransfer中,如果出現跳轉,則是瀏覽器預設的事件被觸發,我們需要使用e.preventDefault()來阻止預設事件。

投放區的事件

對於被拖的元素而言,拖向何處則為投放區,投放區的事件如下:

  • dragenter 被拖放元素進入
  • dragover 被拖放元素移動
  • dragleave 被拖放元素離開
<body>
    <div id="one" style="width: 300px;height: 300px;border: 1px solid red"></div>
    <div id="two" style="width: 100px;height: 100px;border: 1px solid blue" draggable="true"></div>
</body>
<script type="text/javascript">
    one.ondragenter = function(e){
        // e.preventDefault();
        console.log(e);
        one.innerHTML = '開始'
    }
    one.ondragover = function(e){
        one.innerHTML += '拖動中'
    }
    one.ondragleave = function(e){
        one.innerHTML = '結束'
    }
</script>

而drop則是監聽被拖拽物拖拽到投放區並鬆開滑鼠的事件,他可以接收到dataTransfer中的資料,所以我們的頁面內拖拽可以寫成如下效果:

<style type="text/css">
    *{
        box-sizing: border-box;
    }
</style>
<body>
    <div id="one" style="width: 300px;height: 300px;border: 1px solid red"></div>
    <div id="two" style="width: 100px;height: 100px;border: 1px solid blue;display: flex;">
        <div style="width: 50px;height: 100px;border:1px solid black;">第一個</div>
        <div style="width: 50px;height: 100px;border:1px solid pink;">第二個</div>
    </div>
</body>
<script type="text/javascript">
one.ondragover = function(e) {
    e.preventDefault();
}
two.onmousedown = function(e){
    e.target.draggable = true;
    e.target.ondragstart = function(ev) {
        ev.dataTransfer.setData("Text", ev.target.innerHTML);
    }
    e.target.ondragend = function(){
        two.removeChild(this)
    }
}
one.ondrop = function(e) {
    var div = document.createElement('div')
    div.style = "width: 50px;height: 100px;border:1px solid black;"
    div.innerHTML = e.dataTransfer.getData("Text")
    this.appendChild(div)
}
</script>
  • 對於谷歌瀏覽器,e.dataTransfer.setData(key,value)會導致拖拽到投放區域外的時候瀏覽器預設搜尋設定的值。如果需要,我們可以遮蔽它
  • 對於火狐瀏覽器,沒有e.dataTransfer.setData(key,value)還不行。我們可以直接設定鍵值對為null,"";
  • 最新版本的谷歌和火狐瀏覽器沒有發現問題
  • drop事件並不能直接觸發,因為預設的鬆開滑鼠我們的拖拽物會返回原來的位置,並不會掉落,所以我們應該阻止投放區域的預設事件.

拖拽檔案上傳

經過觀察,事件物件中的dataTransfer也存在files屬性,我們可以用熟悉的方法上傳拖拽進來的檔案:

<body>
    <div id="one" style="width: 300px;height: 300px;border: 1px solid red"></div>
</body>
<script type="text/javascript">
one.ondragover = function(e) {
    e.preventDefault();
}
one.ondrop = function(e) {
    e.preventDefault()
    console.log(e.dataTransfer.files[0]);
}
</script>

然後做Ajax檔案上傳即可

one.ondrop = function(e) {
    e.preventDefault()
    var file = e.dataTransfer.files[0];
    var formData = new FormData();
    formData.append("aa", file);
    var xml = new XMLHttpRequest();
    xml.open("post", url, false);
    xml.send(formData);
}

相關文章