67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
import {
|
||
BRAND_KNOWLEDGE_MAX_PREVIEW_IMAGE_BYTES,
|
||
BRAND_KNOWLEDGE_MAX_PREVIEW_SLICE_BYTES,
|
||
BRAND_KNOWLEDGE_MAX_PREVIEW_SLICE_COUNT,
|
||
} from '@/lib/brand-knowledge-file-types'
|
||
import {
|
||
preparePerformanceSurveyImagesInBrowser,
|
||
type PerformanceSurveyBrowserProcessedImage,
|
||
} from '@/lib/performance-survey-image-browser'
|
||
import {
|
||
BRAND_KNOWLEDGE_LEGACY_SERVER_MAX_PIXELS,
|
||
PERFORMANCE_SURVEY_BROWSER_SOURCE_LIMITS,
|
||
readPerformanceSurveySourceImageDimensions,
|
||
} from '@/lib/performance-survey-image-source-guard'
|
||
|
||
export type BrandKnowledgeBrowserPreviewSlice = PerformanceSurveyBrowserProcessedImage & {
|
||
kind: 'slice'
|
||
}
|
||
|
||
export async function prepareBrandKnowledgePreviewInBrowser(
|
||
file: File,
|
||
onProgress?: (label: string) => void,
|
||
options: { signal?: AbortSignal; timeoutMs?: number } = {},
|
||
): Promise<BrandKnowledgeBrowserPreviewSlice[]> {
|
||
const processed = await preparePerformanceSurveyImagesInBrowser(
|
||
[file],
|
||
onProgress,
|
||
{
|
||
profile: 'brand_knowledge_preview',
|
||
signal: options.signal,
|
||
timeoutMs: options.timeoutMs,
|
||
},
|
||
)
|
||
const slices = processed.filter(
|
||
(item): item is BrandKnowledgeBrowserPreviewSlice => item.kind === 'slice',
|
||
)
|
||
if (slices.length === 0) throw new Error('浏览器未生成品牌知识预览切片')
|
||
if (slices.length > BRAND_KNOWLEDGE_MAX_PREVIEW_SLICE_COUNT) {
|
||
throw new Error(`预览图处理后超过 ${BRAND_KNOWLEDGE_MAX_PREVIEW_SLICE_COUNT} 个切片`)
|
||
}
|
||
if (slices.some((slice) => slice.file.size <= 0 || slice.file.size > BRAND_KNOWLEDGE_MAX_PREVIEW_SLICE_BYTES)) {
|
||
throw new Error('预览图处理后的单个切片过大,请先压缩图片后重试')
|
||
}
|
||
const totalBytes = slices.reduce((sum, slice) => sum + slice.file.size, 0)
|
||
if (totalBytes > BRAND_KNOWLEDGE_MAX_PREVIEW_IMAGE_BYTES) {
|
||
throw new Error('预览图处理后的切片总大小超过 50MB,请先压缩图片后重试')
|
||
}
|
||
return slices
|
||
}
|
||
|
||
export async function canUseBrandKnowledgeLegacyServerPreview(file: File) {
|
||
let bytes = new Uint8Array(
|
||
await file.slice(0, PERFORMANCE_SURVEY_BROWSER_SOURCE_LIMITS.headerReadBytes).arrayBuffer(),
|
||
)
|
||
let dimensions = readPerformanceSurveySourceImageDimensions(bytes)
|
||
if (!dimensions && file.size > bytes.byteLength) {
|
||
bytes = new Uint8Array(
|
||
await file.slice(0, PERFORMANCE_SURVEY_BROWSER_SOURCE_LIMITS.extendedHeaderReadBytes).arrayBuffer(),
|
||
)
|
||
dimensions = readPerformanceSurveySourceImageDimensions(bytes)
|
||
}
|
||
if (!dimensions) return false
|
||
return dimensions.width <= PERFORMANCE_SURVEY_BROWSER_SOURCE_LIMITS.maxWidth
|
||
&& dimensions.height <= 90_000
|
||
&& dimensions.width * dimensions.height <= BRAND_KNOWLEDGE_LEGACY_SERVER_MAX_PIXELS
|
||
}
|