Hanye官网
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

image-localizer.ts 2.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import fs from 'fs'
  2. import path from 'path'
  3. import { createHash } from 'crypto'
  4. /**
  5. * 下载并本地化图片
  6. * @param imageUrl 原始图片URL
  7. * @param basePath 保存图片的基础路径
  8. * @returns 本地化后的图片路径
  9. */
  10. export async function localizeImage(imageUrl: string, basePath = 'public/images/remote'): Promise<string> {
  11. // 检查URL是否有效
  12. if (!imageUrl || !imageUrl.startsWith('http')) {
  13. return imageUrl
  14. }
  15. try {
  16. // 创建保存目录
  17. const fullBasePath = path.resolve(process.cwd(), basePath)
  18. if (!fs.existsSync(fullBasePath)) {
  19. fs.mkdirSync(fullBasePath, { recursive: true })
  20. }
  21. // 生成唯一文件名(使用URL的MD5哈希)
  22. const urlHash = createHash('md5').update(imageUrl).digest('hex')
  23. const fileExt = path.extname(new URL(imageUrl).pathname) || '.jpg'
  24. const fileName = `${urlHash}${fileExt}`
  25. const filePath = path.join(fullBasePath, fileName)
  26. // 如果文件已存在,直接返回路径
  27. if (fs.existsSync(filePath)) {
  28. return `/images/remote/${fileName}`
  29. }
  30. // 下载图片
  31. const response = await fetch(imageUrl)
  32. if (!response.ok) {
  33. throw new Error(`下载图片失败: ${response.status} ${response.statusText}`)
  34. }
  35. const buffer = Buffer.from(await response.arrayBuffer())
  36. fs.writeFileSync(filePath, buffer)
  37. // 返回本地URL(相对于public目录)
  38. return `/images/remote/${fileName}`
  39. } catch (error) {
  40. console.error(`本地化图片失败 ${imageUrl}:`, error)
  41. return imageUrl // 失败时返回原始URL
  42. }
  43. }
  44. /**
  45. * 递归处理对象中的所有图片URL
  46. * @param data 需要处理的数据对象或数组
  47. * @param imageFields 指定哪些字段包含图片URL
  48. * @returns 处理后的数据
  49. */
  50. export async function localizeImages(
  51. data: any,
  52. imageFields = ['image', 'imageUrl', 'thumbnail', 'cover', 'avatar', 'photo', 'src']
  53. ): Promise<any> {
  54. if (!data) return data
  55. // 处理数组
  56. if (Array.isArray(data)) {
  57. return Promise.all(data.map(item => localizeImages(item, imageFields)))
  58. }
  59. // 处理对象
  60. if (typeof data === 'object') {
  61. const result = { ...data }
  62. // 处理所有键
  63. for (const [key, value] of Object.entries(result)) {
  64. // 如果是图片字段且值是字符串,本地化图片
  65. if (imageFields.includes(key) && typeof value === 'string') {
  66. result[key] = await localizeImage(value)
  67. }
  68. // 递归处理嵌套对象或数组
  69. else if (typeof value === 'object' && value !== null) {
  70. result[key] = await localizeImages(value, imageFields)
  71. }
  72. }
  73. return result
  74. }
  75. return data
  76. }