Replace Blob with File for file uploads
This commit is contained in:
parent
24637d3db3
commit
cbce560805
@ -39,20 +39,18 @@ export async function getFiles(
|
|||||||
* @param client CurseForge 客户端实例
|
* @param client CurseForge 客户端实例
|
||||||
* @param projectId 项目 ID(数字)
|
* @param projectId 项目 ID(数字)
|
||||||
* @param metadata 已通过 Zod 校验的文件元数据
|
* @param metadata 已通过 Zod 校验的文件元数据
|
||||||
* @param file 要上传的文件 Blob
|
* @param file 要上传的文件
|
||||||
*/
|
*/
|
||||||
export async function uploadFile(
|
export async function uploadFile(
|
||||||
client: CurseForgeClient,
|
client: CurseForgeClient,
|
||||||
projectId: number,
|
projectId: number,
|
||||||
metadata: UploadMetadata,
|
metadata: UploadMetadata,
|
||||||
file: Blob,
|
file: File,
|
||||||
): Promise<UploadResponse> {
|
): Promise<UploadResponse> {
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
form.append("metadata", JSON.stringify(metadata));
|
form.append("metadata", JSON.stringify(metadata));
|
||||||
|
|
||||||
const filename =
|
form.append("file", file, file.name);
|
||||||
file instanceof File ? file.name : "upload.jar";
|
|
||||||
form.append("file", file, filename);
|
|
||||||
|
|
||||||
const result = await client.uploadPost<unknown>(
|
const result = await client.uploadPost<unknown>(
|
||||||
`/api/projects/${encodeURIComponent(projectId)}/upload-file`,
|
`/api/projects/${encodeURIComponent(projectId)}/upload-file`,
|
||||||
|
|||||||
@ -90,12 +90,12 @@ export async function getVersions(
|
|||||||
*
|
*
|
||||||
* @param client Modrinth 客户端实例
|
* @param client Modrinth 客户端实例
|
||||||
* @param data 已通过 Zod 校验的版本元数据(CreatableVersion)
|
* @param data 已通过 Zod 校验的版本元数据(CreatableVersion)
|
||||||
* @param files 文件映射:key 为 multipart 字段名(需与 data.file_parts 一致),value 为文件 Blob
|
* @param files 文件映射:key 为 multipart 字段名(需与 data.file_parts 一致),value 为文件
|
||||||
*/
|
*/
|
||||||
export async function createVersion(
|
export async function createVersion(
|
||||||
client: ModrinthClient,
|
client: ModrinthClient,
|
||||||
data: CreatableVersion,
|
data: CreatableVersion,
|
||||||
files: Record<string, Blob>,
|
files: Record<string, File>,
|
||||||
): Promise<Version> {
|
): Promise<Version> {
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
|
|
||||||
@ -104,16 +104,13 @@ export async function createVersion(
|
|||||||
|
|
||||||
// 逐一添加文件
|
// 逐一添加文件
|
||||||
for (const fieldName of data.file_parts) {
|
for (const fieldName of data.file_parts) {
|
||||||
const blob = files[fieldName];
|
const file = files[fieldName];
|
||||||
if (!blob) {
|
if (!file) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`createVersion: file field "${fieldName}" declared in file_parts but not provided in files`,
|
`createVersion: file field "${fieldName}" declared in file_parts but not provided in files`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// 从 Blob 推断文件名;若无则使用字段名作为回退
|
form.append(fieldName, file, file.name);
|
||||||
const filename =
|
|
||||||
blob instanceof File ? blob.name : `${fieldName}.jar`;
|
|
||||||
form.append(fieldName, blob, filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await client.post<unknown>("/version", form);
|
const result = await client.post<unknown>("/version", form);
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { readFileSync } from "node:fs";
|
import { readFile } from "node:fs/promises";
|
||||||
|
import { basename } from "node:path";
|
||||||
|
|
||||||
export function readJarBlob(filePath: string): Blob {
|
export async function readAsFile(filePath: string): Promise<File> {
|
||||||
try {
|
try {
|
||||||
const buffer = readFileSync(filePath);
|
const buffer = await readFile(filePath);
|
||||||
return new Blob([buffer]);
|
return new File([buffer], basename(filePath));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const msg = err instanceof Error ? err.message : String(err);
|
const msg = err instanceof Error ? err.message : String(err);
|
||||||
throw new Error(`Failed to read file "${filePath}": ${msg}`);
|
throw new Error(`Failed to read file "${filePath}": ${msg}`);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { curseforgeClient } from "@/services/clients";
|
import { curseforgeClient } from "@/services/clients";
|
||||||
import { uploadFile, getGameVersions } from "@/lib/curseforge";
|
import { uploadFile, getGameVersions } from "@/lib/curseforge";
|
||||||
import { resolveVersionName, buildJarPath } from "@/lib/utils/format";
|
import { resolveVersionName, buildJarPath } from "@/lib/utils/format";
|
||||||
import { readJarBlob } from "@/lib/utils/file";
|
import { readAsFile } from "@/lib/utils/file";
|
||||||
import type { UploadMetadata } from "@/types";
|
import type { UploadMetadata } from "@/types";
|
||||||
import type { PlatformContext } from "./types";
|
import type { PlatformContext } from "./types";
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export async function publishCurseForgeVersion(
|
|||||||
mcVersion,
|
mcVersion,
|
||||||
);
|
);
|
||||||
|
|
||||||
const primaryBlob = readJarBlob(primaryPath);
|
const primaryFile = await readAsFile(primaryPath);
|
||||||
|
|
||||||
const gameVersions = await getGameVersions(curseforgeClient);
|
const gameVersions = await getGameVersions(curseforgeClient);
|
||||||
|
|
||||||
@ -51,6 +51,6 @@ export async function publishCurseForgeVersion(
|
|||||||
curseforgeClient,
|
curseforgeClient,
|
||||||
config.curseforge.project_id,
|
config.curseforge.project_id,
|
||||||
metadata,
|
metadata,
|
||||||
primaryBlob,
|
primaryFile,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { modrinthClient } from "@/services/clients";
|
import { modrinthClient } from "@/services/clients";
|
||||||
import { createVersion } from "@/lib/modrinth";
|
import { createVersion } from "@/lib/modrinth";
|
||||||
import { resolveVersionName, buildJarPath } from "@/lib/utils/format";
|
import { resolveVersionName, buildJarPath } from "@/lib/utils/format";
|
||||||
import { readJarBlob } from "@/lib/utils/file";
|
import { readAsFile } from "@/lib/utils/file";
|
||||||
import type { CreatableVersion } from "@/types";
|
import type { CreatableVersion } from "@/types";
|
||||||
import type { PlatformContext } from "./types";
|
import type { PlatformContext } from "./types";
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ export async function publishModrinthVersion(
|
|||||||
mcVersion,
|
mcVersion,
|
||||||
);
|
);
|
||||||
|
|
||||||
const primaryBlob = readJarBlob(primaryPath);
|
const primaryFile = await readAsFile(primaryPath);
|
||||||
const sourceBlob = readJarBlob(sourcePath);
|
const sourceFile = await readAsFile(sourcePath);
|
||||||
|
|
||||||
const data: CreatableVersion = {
|
const data: CreatableVersion = {
|
||||||
project_id: config.modrinth.project_id,
|
project_id: config.modrinth.project_id,
|
||||||
@ -65,7 +65,7 @@ export async function publishModrinthVersion(
|
|||||||
};
|
};
|
||||||
|
|
||||||
await createVersion(modrinthClient, data, {
|
await createVersion(modrinthClient, data, {
|
||||||
primary: primaryBlob,
|
primary: primaryFile,
|
||||||
sources: sourceBlob,
|
sources: sourceFile,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user