Replaced base64 loading of images with blob, small fixes
This commit is contained in:
		@@ -57,7 +57,7 @@ namespace api {
 | 
				
			|||||||
                std::string code = create_totp_qrcode(user, b32_secret);
 | 
					                std::string code = create_totp_qrcode(user, b32_secret);
 | 
				
			||||||
                cbk(dto::Responses::get_tfa_setup_res(b32_secret, code));
 | 
					                cbk(dto::Responses::get_tfa_setup_res(b32_secret, code));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (const std::exception& e) {
 | 
					        } catch (const std::exception&) {
 | 
				
			||||||
            cbk(dto::Responses::get_badreq_res("Validation error"));
 | 
					            cbk(dto::Responses::get_badreq_res("Validation error"));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,6 @@ public:
 | 
				
			|||||||
        METHOD_ADD(fs::download, "/download", drogon::Post, "Login");
 | 
					        METHOD_ADD(fs::download, "/download", drogon::Post, "Login");
 | 
				
			||||||
        METHOD_ADD(fs::download_multi, "/download_multi", drogon::Post, "Login");
 | 
					        METHOD_ADD(fs::download_multi, "/download_multi", drogon::Post, "Login");
 | 
				
			||||||
        METHOD_ADD(fs::download_preview, "/download_preview/{}", drogon::Get, "Login");
 | 
					        METHOD_ADD(fs::download_preview, "/download_preview/{}", drogon::Get, "Login");
 | 
				
			||||||
        METHOD_ADD(fs::download_base64, "/download_base64/{}", drogon::Get, "Login");
 | 
					 | 
				
			||||||
        METHOD_ADD(fs::get_type, "/get_type/{}", drogon::Get, "Login");
 | 
					        METHOD_ADD(fs::get_type, "/get_type/{}", drogon::Get, "Login");
 | 
				
			||||||
    METHOD_LIST_END
 | 
					    METHOD_LIST_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -124,7 +123,6 @@ public:
 | 
				
			|||||||
    void download(req_type, cbk_type);
 | 
					    void download(req_type, cbk_type);
 | 
				
			||||||
    void download_multi(req_type, cbk_type);
 | 
					    void download_multi(req_type, cbk_type);
 | 
				
			||||||
    void download_preview(req_type, cbk_type, uint64_t node);
 | 
					    void download_preview(req_type, cbk_type, uint64_t node);
 | 
				
			||||||
    void download_base64(req_type, cbk_type, uint64_t node);
 | 
					 | 
				
			||||||
    void get_type(req_type, cbk_type, uint64_t node);
 | 
					    void get_type(req_type, cbk_type, uint64_t node);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -554,28 +554,6 @@ namespace api {
 | 
				
			|||||||
        cbk(dto::Responses::get_download_base64_res("data:image/png;base64," + Botan::base64_encode(image)));
 | 
					        cbk(dto::Responses::get_download_base64_res("data:image/png;base64," + Botan::base64_encode(image)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void fs::download_base64(req_type req, cbk_type cbk, uint64_t node) {
 | 
					 | 
				
			||||||
        db::User user = dto::get_user(req);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto inode = get_node_and_validate(user, node);
 | 
					 | 
				
			||||||
        if (!inode.has_value())
 | 
					 | 
				
			||||||
            return cbk(dto::Responses::get_badreq_res("Unknown node"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::filesystem::path p("./files"), name(inode->getValueOfName());
 | 
					 | 
				
			||||||
        p /= std::to_string(inode->getValueOfId());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            std::string mime = mime_type_map.at(name.extension().string());
 | 
					 | 
				
			||||||
            std::ifstream file(p, std::ios::in | std::ios::binary);
 | 
					 | 
				
			||||||
            std::vector<uint8_t> content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            cbk(dto::Responses::get_download_base64_res("data:" + mime + ";base64," + Botan::base64_encode(content)));
 | 
					 | 
				
			||||||
        } catch (const std::exception&) {
 | 
					 | 
				
			||||||
            cbk(dto::Responses::get_badreq_res("Invalid file type"));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void fs::get_type(req_type req, cbk_type cbk, uint64_t node){
 | 
					    void fs::get_type(req_type req, cbk_type cbk, uint64_t node){
 | 
				
			||||||
        db::User user = dto::get_user(req);
 | 
					        db::User user = dto::get_user(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,9 +22,9 @@ namespace dto {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    namespace Responses {
 | 
					    namespace Responses {
 | 
				
			||||||
        struct GetUsersEntry {
 | 
					        struct GetUsersEntry {
 | 
				
			||||||
            GetUsersEntry(int id, bool gitlab, bool tfa, std::string name, db::UserRole role)
 | 
					            GetUsersEntry(uint64_t id, bool gitlab, bool tfa, std::string name, db::UserRole role)
 | 
				
			||||||
                : id(id), gitlab(gitlab), tfa(tfa), name(std::move(name)), role(role) {}
 | 
					                : id(id), gitlab(gitlab), tfa(tfa), name(std::move(name)), role(role) {}
 | 
				
			||||||
            int id;
 | 
					            uint64_t id;
 | 
				
			||||||
            bool gitlab, tfa;
 | 
					            bool gitlab, tfa;
 | 
				
			||||||
            std::string name;
 | 
					            std::string name;
 | 
				
			||||||
            db::UserRole role;
 | 
					            db::UserRole role;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,12 +73,6 @@ export const download_preview = (
 | 
				
			|||||||
): Promise<Responses.DownloadBase64 | Responses.Error> =>
 | 
					): Promise<Responses.DownloadBase64 | Responses.Error> =>
 | 
				
			||||||
	get_token(`/api/fs/download_preview/${node}`, token);
 | 
						get_token(`/api/fs/download_preview/${node}`, token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const download_base64 = (
 | 
					 | 
				
			||||||
	token: string,
 | 
					 | 
				
			||||||
	node: number
 | 
					 | 
				
			||||||
): Promise<Responses.DownloadBase64 | Responses.Error> =>
 | 
					 | 
				
			||||||
	get_token(`/api/fs/download_base64/${node}`, token);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const get_type = (
 | 
					export const get_type = (
 | 
				
			||||||
	token: string,
 | 
						token: string,
 | 
				
			||||||
	node: number
 | 
						node: number
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +1,24 @@
 | 
				
			|||||||
import { ref } from 'vue';
 | 
					import { ref } from 'vue';
 | 
				
			||||||
import { NProgress } from 'naive-ui';
 | 
					import { NProgress } from 'naive-ui';
 | 
				
			||||||
import filesize from 'filesize';
 | 
					import filesize from 'filesize';
 | 
				
			||||||
import { Music, Video } from '@vicons/carbon';
 | 
					import { Music, Video, Image } from '@vicons/carbon';
 | 
				
			||||||
import type { DialogApiInjection } from 'naive-ui/es/dialog/src/DialogProvider';
 | 
					import type { DialogApiInjection } from 'naive-ui/es/dialog/src/DialogProvider';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function createAudioVideoDialog(
 | 
					export default function createBlobDialog(
 | 
				
			||||||
	dialog: DialogApiInjection,
 | 
						dialog: DialogApiInjection,
 | 
				
			||||||
 | 
						audio: boolean,
 | 
				
			||||||
	video: boolean
 | 
						video: boolean
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
	const progress = ref(0);
 | 
						const progress = ref(0);
 | 
				
			||||||
	const total = ref(1);
 | 
						const total = ref(1);
 | 
				
			||||||
	const percentage = ref(0);
 | 
						const percentage = ref(0);
 | 
				
			||||||
	const dia = dialog.create({
 | 
						const dia = dialog.create({
 | 
				
			||||||
		title: video ? 'Loading video...' : 'Loading audio...',
 | 
							title:
 | 
				
			||||||
 | 
								'Loading ' + (video ? 'video' : audio ? 'audio' : 'image') + '...',
 | 
				
			||||||
		closable: false,
 | 
							closable: false,
 | 
				
			||||||
		closeOnEsc: false,
 | 
							closeOnEsc: false,
 | 
				
			||||||
		maskClosable: false,
 | 
							maskClosable: false,
 | 
				
			||||||
		icon: () => (video ? <Video /> : <Music />),
 | 
							icon: () => (video ? <Video /> : audio ? <Music /> : <Image />),
 | 
				
			||||||
		content: () => (
 | 
							content: () => (
 | 
				
			||||||
			<NProgress
 | 
								<NProgress
 | 
				
			||||||
				type="line"
 | 
									type="line"
 | 
				
			||||||
@@ -4,7 +4,7 @@ import { inject, ref, watch } from 'vue';
 | 
				
			|||||||
import { Download, Play } from '@vicons/carbon';
 | 
					import { Download, Play } from '@vicons/carbon';
 | 
				
			||||||
import { useDialog, NGrid, NGi, NButton, NImage, NSpin, NIcon } from 'naive-ui';
 | 
					import { useDialog, NGrid, NGi, NButton, NImage, NSpin, NIcon } from 'naive-ui';
 | 
				
			||||||
import { check_token, FS, isErrorResponse } from '@/api';
 | 
					import { check_token, FS, isErrorResponse } from '@/api';
 | 
				
			||||||
import createAudioVideoDialog from '@/components/FileViewer/AudioVideoDownload';
 | 
					import createBlobDialog from '@/components/FileViewer/BlobDownload';
 | 
				
			||||||
import axios from 'axios';
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps<{
 | 
					const props = defineProps<{
 | 
				
			||||||
@@ -31,11 +31,12 @@ async function download() {
 | 
				
			|||||||
	FS.download_file(token, props.node.id);
 | 
						FS.download_file(token, props.node.id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function loadAudioOrVideo() {
 | 
					async function loadContent() {
 | 
				
			||||||
	const token = await check_token(jwt);
 | 
						const token = await check_token(jwt);
 | 
				
			||||||
	if (!token) return;
 | 
						if (!token) return;
 | 
				
			||||||
	const { progress, total, percentage, dia } = createAudioVideoDialog(
 | 
						const { progress, total, percentage, dia } = createBlobDialog(
 | 
				
			||||||
		dialog,
 | 
							dialog,
 | 
				
			||||||
 | 
							fileType.value === fileTypes.AUDIO,
 | 
				
			||||||
		fileType.value === fileTypes.VIDEO
 | 
							fileType.value === fileTypes.VIDEO
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
	total.value = props.node.size ?? 1;
 | 
						total.value = props.node.size ?? 1;
 | 
				
			||||||
@@ -63,10 +64,8 @@ async function getType(node: Responses.GetNode) {
 | 
				
			|||||||
	const resp = await FS.get_type(token, node.id);
 | 
						const resp = await FS.get_type(token, node.id);
 | 
				
			||||||
	if (isErrorResponse(resp)) return;
 | 
						if (isErrorResponse(resp)) return;
 | 
				
			||||||
	if (resp.type.startsWith('image')) {
 | 
						if (resp.type.startsWith('image')) {
 | 
				
			||||||
		const dataResp = await FS.download_base64(token, node.id);
 | 
					 | 
				
			||||||
		if (isErrorResponse(dataResp)) return;
 | 
					 | 
				
			||||||
		src.value = dataResp.data;
 | 
					 | 
				
			||||||
		fileType.value = fileTypes.IMAGE;
 | 
							fileType.value = fileTypes.IMAGE;
 | 
				
			||||||
 | 
							await loadContent();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (resp.type.startsWith('audio')) fileType.value = fileTypes.AUDIO;
 | 
						if (resp.type.startsWith('audio')) fileType.value = fileTypes.AUDIO;
 | 
				
			||||||
	if (resp.type.startsWith('video')) fileType.value = fileTypes.VIDEO;
 | 
						if (resp.type.startsWith('video')) fileType.value = fileTypes.VIDEO;
 | 
				
			||||||
@@ -95,27 +94,25 @@ watch(
 | 
				
			|||||||
		</n-gi>
 | 
							</n-gi>
 | 
				
			||||||
		<n-gi style="text-align: center">
 | 
							<n-gi style="text-align: center">
 | 
				
			||||||
			<n-spin v-if="fileType === fileTypes.LOADING" size="large" />
 | 
								<n-spin v-if="fileType === fileTypes.LOADING" size="large" />
 | 
				
			||||||
			<n-image
 | 
								<template v-else-if="fileType !== fileTypes.UNKNOWN">
 | 
				
			||||||
				v-else-if="fileType === fileTypes.IMAGE"
 | 
					 | 
				
			||||||
				:src="src"
 | 
					 | 
				
			||||||
				:alt="node.name"
 | 
					 | 
				
			||||||
			/>
 | 
					 | 
				
			||||||
			<template
 | 
					 | 
				
			||||||
				v-else-if="
 | 
					 | 
				
			||||||
					fileType === fileTypes.VIDEO || fileType === fileTypes.AUDIO
 | 
					 | 
				
			||||||
				"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				<video
 | 
									<video
 | 
				
			||||||
					v-if="fileType === fileTypes.VIDEO && src !== ''"
 | 
										v-if="fileType === fileTypes.VIDEO && src !== ''"
 | 
				
			||||||
					:src="src"
 | 
										:src="src"
 | 
				
			||||||
					controls
 | 
										controls
 | 
				
			||||||
 | 
										autoplay
 | 
				
			||||||
				/>
 | 
									/>
 | 
				
			||||||
				<audio
 | 
									<audio
 | 
				
			||||||
					v-else-if="fileType === fileTypes.AUDIO && src !== ''"
 | 
										v-else-if="fileType === fileTypes.AUDIO && src !== ''"
 | 
				
			||||||
					:src="src"
 | 
										:src="src"
 | 
				
			||||||
					controls
 | 
										controls
 | 
				
			||||||
 | 
										autoplay
 | 
				
			||||||
				/>
 | 
									/>
 | 
				
			||||||
				<n-button v-else @click="loadAudioOrVideo">
 | 
									<n-image
 | 
				
			||||||
 | 
										v-else-if="fileType === fileTypes.IMAGE && src !== ''"
 | 
				
			||||||
 | 
										:src="src"
 | 
				
			||||||
 | 
										:alt="node.name"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<n-button v-else-if="fileType !== fileTypes.IMAGE" @click="loadContent">
 | 
				
			||||||
					<template #icon>
 | 
										<template #icon>
 | 
				
			||||||
						<n-icon><Play /></n-icon>
 | 
											<n-icon><Play /></n-icon>
 | 
				
			||||||
					</template>
 | 
										</template>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user