IV를 암호화된 파일 및 썸네일 앞에 합쳐서 전송하도록 변경

This commit is contained in:
static committed 2026-01-11 00:29:59 +09:00
1 parent 5d130204a6
commit b9e6f17b0c
13 files changed
+161 -76

No files matched your search

+10 -10
View File
@@ -5,7 +5,7 @@
import { page } from "$app/state";
import { FullscreenDiv } from "$lib/components/atoms";
import { Categories, IconEntryButton, TopBar } from "$lib/components/molecules";
import { getFileInfo, type FileInfo, type MaybeFileInfo } from "$lib/modules/filesystem";
import { getFileInfo, type MaybeFileInfo } from "$lib/modules/filesystem";
import { captureVideoThumbnail } from "$lib/modules/thumbnail";
import { getFileDownloadState } from "$lib/modules/file";
import { masterKeyStore } from "$lib/stores";
@@ -95,14 +95,12 @@
untrack(() => {
if (!downloadState && !isDownloadRequested) {
isDownloadRequested = true;
requestFileDownload(data.id, info!.contentIv!, info!.dataKey!.key).then(
async (buffer) => {
const blob = await updateViewer(buffer, contentType);
if (!viewerType) {
FileSaver.saveAs(blob, info!.name);
}
},
);
requestFileDownload(data.id, info!.dataKey!.key).then(async (buffer) => {
const blob = await updateViewer(buffer, contentType);
if (!viewerType) {
FileSaver.saveAs(blob, info!.name);
}
});
}
});
}
@@ -110,7 +108,9 @@
$effect(() => {
if (info?.exists && downloadState?.status === "decrypted") {
untrack(() => !isDownloadRequested && updateViewer(downloadState.result!, info!.contentIv!));
untrack(
() => !isDownloadRequested && updateViewer(downloadState.result!, info!.contentType!),
);
}
});
@@ -77,7 +77,7 @@ export const requestThumbnailGeneration = async (fileInfo: FileInfo) => {
await scheduler.schedule(
async () => {
statuses.set(fileInfo.id, "generation-pending");
file = await requestFileDownload(fileInfo.id, fileInfo.contentIv!, fileInfo.dataKey?.key!);
file = await requestFileDownload(fileInfo.id, fileInfo.dataKey?.key!);
return file.byteLength;
},
async () => {
+28 -5
View File
@@ -1,10 +1,15 @@
import { error } from "@sveltejs/kit";
import { z } from "zod";
import { authorize } from "$lib/server/modules/auth";
import { parseRangeHeader, getContentRangeHeader } from "$lib/server/modules/http";
import { getFileStream } from "$lib/server/services/file";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ locals, params }) => {
const downloadHandler = async (
locals: App.Locals,
params: Record<string, string>,
request: Request,
) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = z
@@ -15,11 +20,29 @@ export const GET: RequestHandler = async ({ locals, params }) => {
if (!zodRes.success) error(400, "Invalid path parameters");
const { id } = zodRes.data;
const { encContentStream, encContentSize } = await getFileStream(userId, id);
return new Response(encContentStream as ReadableStream, {
const { encContentStream, range } = await getFileStream(
userId,
id,
parseRangeHeader(request.headers.get("Range")),
);
return {
stream: encContentStream,
headers: {
"Accept-Ranges": "bytes",
"Content-Length": (range.end - range.start + 1).toString(),
"Content-Type": "application/octet-stream",
"Content-Length": encContentSize.toString(),
...getContentRangeHeader(range),
},
});
isRangeRequest: !!range,
};
};
export const GET: RequestHandler = async ({ locals, params, request }) => {
const { stream, headers, isRangeRequest } = await downloadHandler(locals, params, request);
return new Response(stream as ReadableStream, { status: isRangeRequest ? 206 : 200, headers });
};
export const HEAD: RequestHandler = async ({ locals, params, request }) => {
const { headers, isRangeRequest } = await downloadHandler(locals, params, request);
return new Response(null, { status: isRangeRequest ? 206 : 200, headers });
};
@@ -1,10 +1,15 @@
import { error } from "@sveltejs/kit";
import { z } from "zod";
import { authorize } from "$lib/server/modules/auth";
import { parseRangeHeader, getContentRangeHeader } from "$lib/server/modules/http";
import { getFileThumbnailStream } from "$lib/server/services/file";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ locals, params }) => {
const downloadHandler = async (
locals: App.Locals,
params: Record<string, string>,
request: Request,
) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = z
@@ -15,11 +20,29 @@ export const GET: RequestHandler = async ({ locals, params }) => {
if (!zodRes.success) error(400, "Invalid path parameters");
const { id } = zodRes.data;
const { encContentStream, encContentSize } = await getFileThumbnailStream(userId, id);
return new Response(encContentStream as ReadableStream, {
const { encContentStream, range } = await getFileThumbnailStream(
userId,
id,
parseRangeHeader(request.headers.get("Range")),
);
return {
stream: encContentStream,
headers: {
"Accept-Ranges": "bytes",
"Content-Length": (range.end - range.start + 1).toString(),
"Content-Type": "application/octet-stream",
"Content-Length": encContentSize.toString(),
...getContentRangeHeader(range),
},
});
isRangeRequest: !!range,
};
};
export const GET: RequestHandler = async ({ locals, params, request }) => {
const { stream, headers, isRangeRequest } = await downloadHandler(locals, params, request);
return new Response(stream as ReadableStream, { status: isRangeRequest ? 206 : 200, headers });
};
export const HEAD: RequestHandler = async ({ locals, params, request }) => {
const { headers, isRangeRequest } = await downloadHandler(locals, params, request);
return new Response(null, { status: isRangeRequest ? 206 : 200, headers });
};