cista-storage/cista-front/src/components/UploadButton.vue

92 lines
2.9 KiB
Vue

<script setup lang="ts">
import { useDocumentStore } from '@/stores/documents'
import NotificationLoading from '@/components/NotificationLoading.vue'
import { FileAddFilled } from '@ant-design/icons-vue'
import { notification } from 'ant-design-vue';
import type { NotificationPlacement } from 'ant-design-vue';
import { h, ref } from 'vue';
const [api, contextHolder] = notification.useNotification();
const fileUploadButton = ref()
const documentStore = useDocumentStore();
const open = (placement: NotificationPlacement) => openNotification(placement);
const isNotificationOpen = ref(false);
const openNotification = (placement: NotificationPlacement) => {
if(!isNotificationOpen.value){
api.open({
message: `Uploading documents`,
description: h(NotificationLoading),
placement,
duration: 0,
onClose: () => { isNotificationOpen.value = false }
});
isNotificationOpen.value = true;
}
};
function uploadFileHandler() {
fileUploadButton.value.click()
}
async function load(file: File, start: number, end: number): Promise<ArrayBuffer> {
const reader = new FileReader();
const load = new Promise<Event>((resolve) => (reader.onload = resolve));
reader.readAsArrayBuffer(file.slice(start, end));
const event = await load;
if (event.target && event.target instanceof FileReader) {
return event.target.result as ArrayBuffer;
} else {
throw new Error('Error loading file' );
}
}
async function sendChunk(file :File, start: number, end: number) {
const ws = documentStore.wsUpload;
if(ws){
const chunk = await load(file, start, end)
ws.send(JSON.stringify({
name: file.name,
size: file.size,
start: start,
end: end
}))
ws.send(chunk)
}
}
async function uploadFileChangeHandler(event: Event) {
const target = event.target as HTMLInputElement;
const chunkSize = 1 << 20
if (target && target.files && target.files.length > 0) {
const file = target.files[0];
const numChunks = Math.ceil(file.size / chunkSize)
const document = documentStore.pushUploadingDocuments(file.name)
open('bottomRight')
for (let i = 0; i < numChunks; i++) {
const start = i * chunkSize
const end = Math.min(file.size, start + chunkSize)
const res = await sendChunk(file, start, end)
console.log( 'progress: '+ ( ( 100 * (i + 1) ) / numChunks) )
console.log( 'Num Chunks: '+ numChunks )
documentStore.updateUploadingDocuments( document.key, ((100 * (i + 1) ) / numChunks))
}
}
}
</script>
<template>
<a-tooltip title="Upload files from disk">
<a-button @click="uploadFileHandler" type="text" class="action-button" :icon="h(FileAddFilled)" />
<input ref="fileUploadButton" @change="uploadFileChangeHandler" class="upload-input" type="file" onclick="this.value=null;" />
</a-tooltip>
<contextHolder />
</template>
<style scoped>
/* Extends styles from HeaderMain.vue too */
.upload-input{
display: none;
}
</style>