65 lines
3.0 KiB
TypeScript
65 lines
3.0 KiB
TypeScript
import { randomUUID } from 'crypto'
|
|
import { mkdir } from 'fs/promises'
|
|
import path from 'path'
|
|
import { downloadS3ObjectToFile } from '@/lib/s3'
|
|
import { resolveStoredUploadPath } from '@/lib/upload-paths'
|
|
import { buildPublicDisplayUrl, buildWhiteBackgroundPublicDisplayPathFromAssetPath } from '@/lib/public-display'
|
|
import { existsSync } from 'fs'
|
|
|
|
const MATERIAL_FILE_FIELDS = [
|
|
'previewUrl', 'zipFilePath', 'zipFileName', 'videoSourceUrl',
|
|
'videoPreview540Url', 'videoPreviewClipUrl', 'videoCoverUrl',
|
|
] as const
|
|
|
|
/** 将已公开的存储对象改为受素材访问权限保护的独立文件。 */
|
|
export async function prepareOperationsGMaterialFiles(
|
|
material: Record<string, any>,
|
|
assets: Array<{ id: string; fileUrl: string }>,
|
|
skus: Array<{ id: string; filePath: string; previewUrl: string | null }> = [],
|
|
) {
|
|
const replacements = new Map<string, string>()
|
|
const copyUrl = async (url: string) => {
|
|
if (!/^https?:\/\//i.test(url)) return url
|
|
const existing = replacements.get(url)
|
|
if (existing) return existing
|
|
const fileName = `${randomUUID()}${path.posix.extname(new URL(url).pathname)}`
|
|
const storedPath = path.posix.join('uploads', 'materials', material.id, 'protected-display', fileName)
|
|
const destination = resolveStoredUploadPath(storedPath)
|
|
await mkdir(path.dirname(destination), { recursive: true })
|
|
await downloadS3ObjectToFile(url, destination)
|
|
replacements.set(url, storedPath)
|
|
return storedPath
|
|
}
|
|
const materialFiles: Record<string, string | string[]> = {}
|
|
for (const field of MATERIAL_FILE_FIELDS) {
|
|
if (material[field]) materialFiles[field] = await copyUrl(material[field])
|
|
}
|
|
if (Array.isArray(material.displayImages)) {
|
|
materialFiles.displayImages = []
|
|
for (const url of material.displayImages) materialFiles.displayImages.push(await copyUrl(url))
|
|
}
|
|
const assetFiles = []
|
|
for (const asset of assets) {
|
|
const fileUrl = await copyUrl(asset.fileUrl)
|
|
if (fileUrl !== asset.fileUrl) assetFiles.push({ id: asset.id, fileUrl })
|
|
const previewPath = buildWhiteBackgroundPublicDisplayPathFromAssetPath(asset.fileUrl)
|
|
const publicPreview = previewPath && /\.webp$/i.test(previewPath) ? buildPublicDisplayUrl(previewPath) : null
|
|
if (previewPath && publicPreview) {
|
|
const storedPath = path.posix.join('uploads', 'materials', material.id, 'protected-display', previewPath)
|
|
const destination = resolveStoredUploadPath(storedPath)
|
|
if (!existsSync(destination)) {
|
|
await mkdir(path.dirname(destination), { recursive: true })
|
|
await downloadS3ObjectToFile(publicPreview, destination)
|
|
}
|
|
replacements.set(publicPreview, storedPath)
|
|
}
|
|
}
|
|
const skuFiles = []
|
|
for (const sku of skus) {
|
|
const filePath = await copyUrl(sku.filePath)
|
|
const previewUrl = sku.previewUrl ? await copyUrl(sku.previewUrl) : sku.previewUrl
|
|
if (filePath !== sku.filePath || previewUrl !== sku.previewUrl) skuFiles.push({ id: sku.id, filePath, previewUrl })
|
|
}
|
|
return { materialFiles, assetFiles, skuFiles, publicUrls: Array.from(replacements.keys()) }
|
|
}
|