fix: improve toutiao image uploads

This commit is contained in:
2026-06-18 20:47:41 +08:00
parent 31c4dd9358
commit 4fa5adc25a
6 changed files with 77 additions and 16 deletions
@@ -19,9 +19,23 @@ export interface CropRect {
height: number
}
const passthroughImageTypes = new Set(['image/png', 'image/jpeg', 'image/jpg', 'image/gif'])
export type AssetImageFormat = 'png' | 'jpg' | 'jpeg'
function buildDesktopAssetFallbackURL(publicAssetUrl: URL): string | null {
export interface FetchImageAssetBlobOptions extends AdapterFetchOptions {
preferredFormat?: AssetImageFormat
passthroughTypes?: string[]
}
const defaultPassthroughImageTypes = new Set(['image/png', 'image/jpeg', 'image/jpg', 'image/gif'])
function normalizeAssetImageFormat(format: AssetImageFormat | undefined): AssetImageFormat {
return format === 'jpg' || format === 'jpeg' ? 'jpg' : 'png'
}
function buildDesktopAssetFallbackURL(
publicAssetUrl: URL,
preferredFormat: AssetImageFormat,
): string | null {
if (!publicAssetUrl.pathname.startsWith('/api/public/assets/')) {
return null
}
@@ -35,11 +49,14 @@ function buildDesktopAssetFallbackURL(publicAssetUrl: URL): string | null {
publicAssetUrl.searchParams.forEach((value, key) => {
fallbackURL.searchParams.set(key, value)
})
fallbackURL.searchParams.set('format', 'png')
fallbackURL.searchParams.set('format', preferredFormat)
return fallbackURL.toString()
}
export function buildAssetURLCandidates(sourceUrl: string): string[] {
export function buildAssetURLCandidates(
sourceUrl: string,
options: { preferredFormat?: AssetImageFormat } = {},
): string[] {
const trimmed = sourceUrl.trim()
if (!trimmed) {
return []
@@ -57,16 +74,17 @@ export function buildAssetURLCandidates(sourceUrl: string): string[] {
}
try {
const preferredFormat = normalizeAssetImageFormat(options.preferredFormat)
const parsed = new URL(trimmed, resolveDesktopApiURL('/'))
if (parsed.pathname.startsWith('/api/')) {
const apiAssetUrl = new URL(resolveDesktopApiURL(`${parsed.pathname}${parsed.search}`))
if (apiAssetUrl.pathname.startsWith('/api/public/assets/')) {
apiAssetUrl.searchParams.set('format', 'png')
apiAssetUrl.searchParams.set('format', preferredFormat)
}
pushCandidate(apiAssetUrl.toString())
const desktopAssetFallbackURL = buildDesktopAssetFallbackURL(apiAssetUrl)
const desktopAssetFallbackURL = buildDesktopAssetFallbackURL(apiAssetUrl, preferredFormat)
if (desktopAssetFallbackURL) {
pushCandidate(desktopAssetFallbackURL)
}
@@ -100,9 +118,17 @@ function fileNameForImageType(sourceType: string): string {
export async function fetchImageAssetBlob(
sourceUrl: string,
options: AdapterFetchOptions = {},
options: FetchImageAssetBlobOptions = {},
): Promise<ImageAssetBlob | null> {
for (const candidate of buildAssetURLCandidates(sourceUrl)) {
const passthroughImageTypes = new Set(
(options.passthroughTypes ?? [...defaultPassthroughImageTypes]).map((type) =>
type.toLowerCase(),
),
)
for (const candidate of buildAssetURLCandidates(sourceUrl, {
preferredFormat: options.preferredFormat,
})) {
const response = await (
shouldUseDesktopAssetFetch(candidate)
? fetchDesktopApiURL(candidate, {