@@ -84,28 +84,31 @@ export async function upload_file(
 | 
			
		||||
	token: string,
 | 
			
		||||
	file: UploadFile,
 | 
			
		||||
	onProgress: (progressEvent: ProgressEvent) => void
 | 
			
		||||
): Promise<Responses.Success | Responses.Error> {
 | 
			
		||||
): Promise<[Responses.Success | Responses.Error, boolean]> {
 | 
			
		||||
	const node = await create_file(token, file.parent, file.file.name);
 | 
			
		||||
	if (isErrorResponse(node)) return node;
 | 
			
		||||
	if (isErrorResponse(node)) return [node, false];
 | 
			
		||||
	if ('exists' in node && !node.isFile)
 | 
			
		||||
		return { statusCode: 400, message: 'File exists as folder' };
 | 
			
		||||
		return [{ statusCode: 400, message: 'File exists as folder' }, false];
 | 
			
		||||
 | 
			
		||||
	return axios
 | 
			
		||||
		.post(`/api/fs/upload/${node.id}`, file.file, {
 | 
			
		||||
			headers: {
 | 
			
		||||
				Authorization: 'Bearer ' + token,
 | 
			
		||||
				'Content-type': 'multipart/form-data'
 | 
			
		||||
			},
 | 
			
		||||
			onUploadProgress: onProgress
 | 
			
		||||
		})
 | 
			
		||||
		.then((res) => {
 | 
			
		||||
			console.log(res);
 | 
			
		||||
			return res.data;
 | 
			
		||||
		})
 | 
			
		||||
		.catch((err) => {
 | 
			
		||||
			console.log(err);
 | 
			
		||||
			return err.response.data;
 | 
			
		||||
		});
 | 
			
		||||
	return [
 | 
			
		||||
		await axios
 | 
			
		||||
			.post(`/api/fs/upload/${node.id}`, file.file, {
 | 
			
		||||
				headers: {
 | 
			
		||||
					Authorization: 'Bearer ' + token,
 | 
			
		||||
					'Content-type': 'multipart/form-data'
 | 
			
		||||
				},
 | 
			
		||||
				onUploadProgress: onProgress
 | 
			
		||||
			})
 | 
			
		||||
			.then((res) => {
 | 
			
		||||
				console.log(res);
 | 
			
		||||
				return res.data;
 | 
			
		||||
			})
 | 
			
		||||
			.catch((err) => {
 | 
			
		||||
				console.log(err);
 | 
			
		||||
				return err.response.data;
 | 
			
		||||
			}),
 | 
			
		||||
		'exists' in node
 | 
			
		||||
	];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function download_file(token: string, id: number) {
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ async function startDelete() {
 | 
			
		||||
			await resp.body.pipeTo(logWriter);
 | 
			
		||||
		} catch (err) {
 | 
			
		||||
			log.value += `Error: ${err}\n`;
 | 
			
		||||
			logInst.value?.scrollTo({ position: 'top' });
 | 
			
		||||
			logInst.value?.scrollTo({ position: 'bottom', slient: true });
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -115,6 +115,8 @@ watch(
 | 
			
		||||
					v-else-if="fileType === fileTypes.IMAGE && src !== ''"
 | 
			
		||||
					:src="src"
 | 
			
		||||
					:alt="node.name"
 | 
			
		||||
					:img-props="{ style: 'max-width: 80vw; max-height: 70vh;' }"
 | 
			
		||||
					object-fit="contain"
 | 
			
		||||
				/>
 | 
			
		||||
				<iframe
 | 
			
		||||
					v-else-if="fileType === fileTypes.IFRAME && src !== ''"
 | 
			
		||||
@@ -137,4 +139,4 @@ watch(
 | 
			
		||||
	</n-grid>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped></style>
 | 
			
		||||
<style scoped lang="scss"></style>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import filesize from 'filesize';
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
	file: UploadFile;
 | 
			
		||||
	abort: boolean;
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const progress = ref(0);
 | 
			
		||||
@@ -15,13 +16,26 @@ const percentage = ref(0);
 | 
			
		||||
const err = ref('');
 | 
			
		||||
const status = ref<Status>('info');
 | 
			
		||||
const shown = ref(true);
 | 
			
		||||
const existed = ref(false);
 | 
			
		||||
 | 
			
		||||
async function startUpload(token: string, done: () => void) {
 | 
			
		||||
	const resp = await FS.upload_file(token, props.file, (e) => {
 | 
			
		||||
	let sendDone = false;
 | 
			
		||||
	if (props.abort) {
 | 
			
		||||
		done();
 | 
			
		||||
		shown.value = false;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	const resp_tuple = await FS.upload_file(token, props.file, (e) => {
 | 
			
		||||
		progress.value = e.loaded;
 | 
			
		||||
		percentage.value = (e.loaded / e.total) * 100;
 | 
			
		||||
		if (e.loaded == e.total) done();
 | 
			
		||||
		if (e.loaded == e.total) {
 | 
			
		||||
			sendDone = true;
 | 
			
		||||
			done();
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
	const resp = resp_tuple[0];
 | 
			
		||||
	existed.value = resp_tuple[1];
 | 
			
		||||
	if (!sendDone) done();
 | 
			
		||||
	percentage.value = 100;
 | 
			
		||||
	if (isErrorResponse(resp)) {
 | 
			
		||||
		err.value = resp.message ?? 'Error';
 | 
			
		||||
@@ -60,6 +74,12 @@ defineExpose({
 | 
			
		||||
			<div v-else-if="err !== ''">
 | 
			
		||||
				{{ file.fullName }} - Error: {{ err }}
 | 
			
		||||
			</div>
 | 
			
		||||
			<div v-else-if="existed">
 | 
			
		||||
				{{ file.fullName }} - Old file overridden
 | 
			
		||||
			</div>
 | 
			
		||||
			<div v-else-if="status !== 'success'">
 | 
			
		||||
				{{ file.fullName }} - Processing...
 | 
			
		||||
			</div>
 | 
			
		||||
			<div v-else>{{ file.fullName }} - Completed</div>
 | 
			
		||||
			<n-progress
 | 
			
		||||
				type="line"
 | 
			
		||||
 
 | 
			
		||||
@@ -3,20 +3,29 @@ import type { TokenInjectType, UploadFile } from '@/api';
 | 
			
		||||
import { ref, inject } from 'vue';
 | 
			
		||||
import { update_token } from '@/api';
 | 
			
		||||
import UploadEntry from '@/components/UploadDialog/UploadEntry.vue';
 | 
			
		||||
import { NCard } from 'naive-ui';
 | 
			
		||||
import { NCard, NButton } from 'naive-ui';
 | 
			
		||||
import semaphore from 'semaphore';
 | 
			
		||||
 | 
			
		||||
const jwt = inject<TokenInjectType>('jwt') as TokenInjectType;
 | 
			
		||||
 | 
			
		||||
const entries = ref<typeof UploadEntry[]>([]);
 | 
			
		||||
 | 
			
		||||
const abortUpload = ref(false);
 | 
			
		||||
 | 
			
		||||
async function startUpload() {
 | 
			
		||||
	const token = await update_token(jwt);
 | 
			
		||||
	if (!token) return;
 | 
			
		||||
	const ents: typeof UploadEntry[] = entries.value;
 | 
			
		||||
	const allProms: Promise<void>[] = [];
 | 
			
		||||
	const uploadSem = semaphore(5);
 | 
			
		||||
	for (const entry of ents) {
 | 
			
		||||
		await new Promise<void>((resolve) =>
 | 
			
		||||
			allProms.push(entry.startUpload(token, resolve))
 | 
			
		||||
		allProms.push(
 | 
			
		||||
			new Promise<void>((resolve) => {
 | 
			
		||||
				uploadSem.take(async () => {
 | 
			
		||||
					await entry.startUpload(token, () => uploadSem.leave());
 | 
			
		||||
					resolve();
 | 
			
		||||
				});
 | 
			
		||||
			})
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
	await Promise.all(allProms);
 | 
			
		||||
@@ -32,11 +41,13 @@ defineProps<{
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<n-card title="Uploading files" style="margin: 20px">
 | 
			
		||||
		<n-button type="error" @click="abortUpload = true">Abort</n-button>
 | 
			
		||||
		<UploadEntry
 | 
			
		||||
			v-for="f in files"
 | 
			
		||||
			:key="f.file.name"
 | 
			
		||||
			ref="entries"
 | 
			
		||||
			:file="f"
 | 
			
		||||
			:abort="abortUpload"
 | 
			
		||||
		/>
 | 
			
		||||
	</n-card>
 | 
			
		||||
</template>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user