Drag and Drop Multiple File Upload UI [Vue.js]

  • このエントリーをはてなブックマークに追加
  • Pocket

Vue.jsでDrag and DropでMultipleなFileUploadモジュールを作りました。
gifのような動作でファイルのアップロードができるUIです。

上記のイメージのように、このFileUploadUIでは下記の機能をサポートしました。

☑️ファイル選択(複数)
☑️Drag and Drop(複数)
☑️ファイル追加
☑️ファイル削除

このサンプルでは送信ボタンを押下したときにファイルのサーバへのアップロードが開始されます。
今後Drag and Drop時にサーバーへアップロードする機能を追加する予定です。

デモ

Drop files or Browse
  • {{ file.name }}

ソースコード

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" rel="stylesheet" />
<div id="drag_drop_app" class="file_uploader_module">
    <input type="file" ref="file_upload" style="display: none" @change="onFileChange" multiple>
    <div class="drop_area" @dragenter="dragEnter" @dragleave="dragLeave" @dragover.prevent @drop.prevent="dropFile"
        :class="{enter: isEnter}" type="button" @click="$refs.file_upload.click()">
        <i class="fas fa-arrow-circle-up text-6xl mb-3 fa-5x upload-icon"></i>
        <b>Drop files or Browse</b>
    </div>
    <ul class="flex">
        <li class="flex-col" v-for="(file,index) in files" :key="index" @click="deleteFile(index)">
            <div style="position: relative;">
            </div>
            <div class="file-box" style="display: block;">
                <span>
                    {{ file.name }}
                <i class="fa fa-times delete-mark"></i>
</span>
            </div>
        </li>
    </ul>
    <div v-show="files.length">
        <button class="button" @clikc="sendFile">Send</button>
    </div>
</div>
const drag_drop_app = new Vue({
    el: "#drag_drop_app",
    data: {
        isEnter: false,
        files: []
    },
    methods: {
        dragEnter() {
            this.isEnter = true;
        },
        dragLeave() {
            this.isEnter = false;
        },
        dragOver() {
        },
        dropFile() {
            this.files.push(...event.dataTransfer.files)
            this.isEnter = false;
        },
        deleteFile(index) {
            this.files.splice(index, 1)
        },
        upload: function () {
            // FormData を利用して File を POST する
            let formData = new FormData();
            formData.append('files', this.uploadFile);
            let config = {
                headers: {
                    'content-type': 'multipart/form-data'
                }
            };
            axios
                .post('yourUploadUrl', formData, config)
                .then(function (response) {
                })
                .catch(function (error) {
                })
        },
        sendFile() {
            this.files.forEach(file => {
                let form = new FormData()
                form.append('file', file)
                axios.post('url', form).then(response => {
                    console.log(response.data)
                }).catch(error => {
                    console.log(error)
                })
            })
        },
        btnclick() {
            this.$refs.input.click();
        },
        onFileChange(e) {
            let files = e.target.files || e.dataTransfer.files;
            this.files.push(...files)
            console.log(files)
        }
    }
})
/* NEW FILE DRAG AND DROP MODULE */
:root {
    --background-color:#f3f3f3;
    --background-color-hover:#b9b9b9;
    --border-color:#6d6d6d;
    --border-color-hover:#757575;
    --line-border: 2px;
    --text-color-dark: #505050;
}

.file_uploader_module {
    margin: 15px;
}

.drop_area {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    max-width: 700px;
    min-height: 150px;
    border: 5px dashed var(--border-color);
    background-color:var(--background-color);
    color: var(--text-color-dark);
    border-radius: 20px;
    box-sizing: border-box;
    transition: background-color 160ms ease;
    font-weight:bold;
}

.enter {
    border: 5px dashed var(--border-color-hover);
    background-color: var(--background-color-hover);
}

ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
}

.flex {
    display: flex;
    align-items: center;
}

.flex-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin: 0.5em;
    font-size: 10px;
}

.button {
    padding: 0.5em 1.5em;
    background-color:var(--background-color);
    color: var(--text-color-dark);
    font-size: 14px;
    font-weight: bold;
    border-radius: 5px;
    border: 3px solid var(--border-color);
}

.upload {
    color :var(--text-color-dark);
}

.file-box{
    font-size: 15px;
    padding: 2px 8px;
    border: 3px solid var(--border-color);
    background-color:var(--background-color);
    color: var(--text-color-dark);
    font-weight:bold;
}
.delete-mark {
    font-size: 20px;
    color: var(--text-color-dark);
    padding-left:20px;
    vertical-align: middle;
}

参考

【vue.js】ドラッグ&ドロップでファイルアップロード|REFFECT

  • このエントリーをはてなブックマークに追加
  • Pocket

SNSでもご購読できます。

コメントを残す

*