mirror of https://github.com/openclaw/openclaw.git
refactor: deduplicate media store writes
This commit is contained in:
parent
f4ed317083
commit
a37e25fa21
|
|
@ -255,6 +255,48 @@ export type SavedMedia = {
|
||||||
contentType?: string;
|
contentType?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function buildSavedMediaId(params: {
|
||||||
|
baseId: string;
|
||||||
|
ext: string;
|
||||||
|
originalFilename?: string;
|
||||||
|
}): string {
|
||||||
|
if (!params.originalFilename) {
|
||||||
|
return params.ext ? `${params.baseId}${params.ext}` : params.baseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const base = path.parse(params.originalFilename).name;
|
||||||
|
const sanitized = sanitizeFilename(base);
|
||||||
|
return sanitized
|
||||||
|
? `${sanitized}---${params.baseId}${params.ext}`
|
||||||
|
: `${params.baseId}${params.ext}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSavedMediaResult(params: {
|
||||||
|
dir: string;
|
||||||
|
id: string;
|
||||||
|
size: number;
|
||||||
|
contentType?: string;
|
||||||
|
}): SavedMedia {
|
||||||
|
return {
|
||||||
|
id: params.id,
|
||||||
|
path: path.join(params.dir, params.id),
|
||||||
|
size: params.size,
|
||||||
|
contentType: params.contentType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeSavedMediaBuffer(params: {
|
||||||
|
dir: string;
|
||||||
|
id: string;
|
||||||
|
buffer: Buffer;
|
||||||
|
}): Promise<string> {
|
||||||
|
const dest = path.join(params.dir, params.id);
|
||||||
|
await retryAfterRecreatingDir(params.dir, () =>
|
||||||
|
fs.writeFile(dest, params.buffer, { mode: MEDIA_FILE_MODE }),
|
||||||
|
);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
export type SaveMediaSourceErrorCode =
|
export type SaveMediaSourceErrorCode =
|
||||||
| "invalid-path"
|
| "invalid-path"
|
||||||
| "not-found"
|
| "not-found"
|
||||||
|
|
@ -321,20 +363,19 @@ export async function saveMediaSource(
|
||||||
filePath: source,
|
filePath: source,
|
||||||
});
|
});
|
||||||
const ext = extensionForMime(mime) ?? path.extname(new URL(source).pathname);
|
const ext = extensionForMime(mime) ?? path.extname(new URL(source).pathname);
|
||||||
const id = ext ? `${baseId}${ext}` : baseId;
|
const id = buildSavedMediaId({ baseId, ext });
|
||||||
const finalDest = path.join(dir, id);
|
const finalDest = path.join(dir, id);
|
||||||
await fs.rename(tempDest, finalDest);
|
await fs.rename(tempDest, finalDest);
|
||||||
return { id, path: finalDest, size, contentType: mime };
|
return buildSavedMediaResult({ dir, id, size, contentType: mime });
|
||||||
}
|
}
|
||||||
// local path
|
// local path
|
||||||
try {
|
try {
|
||||||
const { buffer, stat } = await readLocalFileSafely({ filePath: source, maxBytes: MAX_BYTES });
|
const { buffer, stat } = await readLocalFileSafely({ filePath: source, maxBytes: MAX_BYTES });
|
||||||
const mime = await detectMime({ buffer, filePath: source });
|
const mime = await detectMime({ buffer, filePath: source });
|
||||||
const ext = extensionForMime(mime) ?? path.extname(source);
|
const ext = extensionForMime(mime) ?? path.extname(source);
|
||||||
const id = ext ? `${baseId}${ext}` : baseId;
|
const id = buildSavedMediaId({ baseId, ext });
|
||||||
const dest = path.join(dir, id);
|
await writeSavedMediaBuffer({ dir, id, buffer });
|
||||||
await retryAfterRecreatingDir(dir, () => fs.writeFile(dest, buffer, { mode: MEDIA_FILE_MODE }));
|
return buildSavedMediaResult({ dir, id, size: stat.size, contentType: mime });
|
||||||
return { id, path: dest, size: stat.size, contentType: mime };
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof SafeOpenError) {
|
if (err instanceof SafeOpenError) {
|
||||||
throw toSaveMediaSourceError(err);
|
throw toSaveMediaSourceError(err);
|
||||||
|
|
@ -359,19 +400,7 @@ export async function saveMediaBuffer(
|
||||||
const headerExt = extensionForMime(contentType?.split(";")[0]?.trim() ?? undefined);
|
const headerExt = extensionForMime(contentType?.split(";")[0]?.trim() ?? undefined);
|
||||||
const mime = await detectMime({ buffer, headerMime: contentType });
|
const mime = await detectMime({ buffer, headerMime: contentType });
|
||||||
const ext = headerExt ?? extensionForMime(mime) ?? "";
|
const ext = headerExt ?? extensionForMime(mime) ?? "";
|
||||||
|
const id = buildSavedMediaId({ baseId: uuid, ext, originalFilename });
|
||||||
let id: string;
|
await writeSavedMediaBuffer({ dir, id, buffer });
|
||||||
if (originalFilename) {
|
return buildSavedMediaResult({ dir, id, size: buffer.byteLength, contentType: mime });
|
||||||
// Embed original name: {sanitized}---{uuid}.ext
|
|
||||||
const base = path.parse(originalFilename).name;
|
|
||||||
const sanitized = sanitizeFilename(base);
|
|
||||||
id = sanitized ? `${sanitized}---${uuid}${ext}` : `${uuid}${ext}`;
|
|
||||||
} else {
|
|
||||||
// Legacy: just UUID
|
|
||||||
id = ext ? `${uuid}${ext}` : uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dest = path.join(dir, id);
|
|
||||||
await retryAfterRecreatingDir(dir, () => fs.writeFile(dest, buffer, { mode: MEDIA_FILE_MODE }));
|
|
||||||
return { id, path: dest, size: buffer.byteLength, contentType: mime };
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue