chore: upgrade onlyoffice to 9.2.1
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import supabaseAdmin from "@/lib/supabase/admin";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const parseStoragePath = (fileUrl: string) => {
|
||||
try {
|
||||
const url = new URL(fileUrl);
|
||||
const segments = url.pathname.split("/").filter(Boolean);
|
||||
const objectIdx = segments.findIndex((seg) => seg === "object");
|
||||
if (objectIdx === -1 || objectIdx + 2 >= segments.length) return null;
|
||||
// pattern 1: /storage/v1/object/public/<bucket>/<path...>
|
||||
if (segments[objectIdx + 1] === "public") {
|
||||
const bucket = segments[objectIdx + 2];
|
||||
const path = segments.slice(objectIdx + 3).join("/");
|
||||
return { bucket, path };
|
||||
}
|
||||
// pattern 2: /storage/v1/object/sign/<bucket>/<path...> (token in query)
|
||||
if (segments[objectIdx + 1] === "sign") {
|
||||
const bucket = segments[objectIdx + 2];
|
||||
const path = segments.slice(objectIdx + 3).join("/");
|
||||
return { bucket, path };
|
||||
}
|
||||
return null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const fileUrl = searchParams.get("fileUrl");
|
||||
const fileName = searchParams.get("fileName") ?? undefined;
|
||||
const forOnlyOffice = searchParams.get("for") === "onlyoffice";
|
||||
const hostOverride = process.env.NEXT_PUBLIC_ONLYOFFICE_STORAGE_HOST_OVERRIDE;
|
||||
if (searchParams.get("debug") === "1") {
|
||||
return NextResponse.json({
|
||||
keyLen: (process.env.SUPABASE_SERVICE_ROLE_KEY || "").length,
|
||||
url: process.env.SUPABASE_URL,
|
||||
});
|
||||
}
|
||||
|
||||
if (!fileUrl) {
|
||||
return NextResponse.json({ error: "缺少 fileUrl" }, { status: 400 });
|
||||
}
|
||||
|
||||
const parsed = parseStoragePath(fileUrl);
|
||||
if (!parsed) {
|
||||
return NextResponse.json({ error: "无法解析 Supabase 存储路径" }, { status: 400 });
|
||||
}
|
||||
|
||||
const { bucket, path } = parsed;
|
||||
|
||||
const { data, error } = await supabaseAdmin.storage
|
||||
.from(bucket)
|
||||
.createSignedUrl(path, 60 * 60, { download: fileName });
|
||||
|
||||
if (error || !data?.signedUrl) {
|
||||
return NextResponse.json({ error: error?.message ?? "生成签名 URL 失败" }, { status: 500 });
|
||||
}
|
||||
|
||||
let signedUrl = data.signedUrl;
|
||||
if (
|
||||
forOnlyOffice &&
|
||||
hostOverride &&
|
||||
(signedUrl.includes("127.0.0.1") || signedUrl.includes("localhost"))
|
||||
) {
|
||||
try {
|
||||
const url = new URL(signedUrl);
|
||||
url.hostname = hostOverride;
|
||||
signedUrl = url.toString();
|
||||
} catch {
|
||||
// ignore parse errors
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({ signedUrl });
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { extname } from "path";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const MEDIA_BUCKET = process.env.NEXT_PUBLIC_SUPABASE_MEDIA_BUCKET ?? "media";
|
||||
const DOC_BUCKET = process.env.NEXT_PUBLIC_SUPABASE_DOC_BUCKET ?? "documents";
|
||||
|
||||
const resolveAssetType = (mime: string): "image" | "video" | "audio" | "file" => {
|
||||
if (mime.startsWith("image/")) return "image";
|
||||
@@ -41,7 +41,7 @@ export async function POST(request: Request) {
|
||||
const path = `${workspaceId}/${Date.now()}-${uniqueId}${extension}`;
|
||||
const assetType = resolveAssetType(file.type || "");
|
||||
|
||||
const { error: uploadError } = await supabase.storage.from(MEDIA_BUCKET).upload(path, buffer, {
|
||||
const { error: uploadError } = await supabase.storage.from(DOC_BUCKET).upload(path, buffer, {
|
||||
contentType: file.type,
|
||||
upsert: false,
|
||||
});
|
||||
@@ -50,17 +50,17 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ error: uploadError.message }, { status: 500 });
|
||||
}
|
||||
|
||||
const {
|
||||
data: { publicUrl },
|
||||
} = supabase.storage.from(MEDIA_BUCKET).getPublicUrl(path);
|
||||
// 为私有桶生成临时访问链接(7 天);前端可在需要时通过 /api/media/signed-url 刷新
|
||||
const { data: signed } = await supabase.storage.from(DOC_BUCKET).createSignedUrl(path, 60 * 60 * 24 * 7);
|
||||
const signedUrl = signed?.signedUrl ?? "";
|
||||
|
||||
const { data: asset, error } = await supabase
|
||||
.from("media_assets")
|
||||
.insert({
|
||||
workspace_id: workspaceId,
|
||||
document_id: documentId,
|
||||
file_url: publicUrl,
|
||||
thumbnail_url: publicUrl,
|
||||
file_url: signedUrl,
|
||||
thumbnail_url: signedUrl,
|
||||
asset_type: assetType,
|
||||
file_name: file.name,
|
||||
file_size: file.size,
|
||||
|
||||
Reference in New Issue
Block a user