|
| 1 | +import { Readable } from 'stream' |
| 2 | +import { isString, merge, pick } from 'lodash-es' |
| 3 | +import path from 'path' |
| 4 | +import httpClient from '@/infra/http-client' |
| 5 | +import { ExtConst } from '@/ctx/ext-const' |
| 6 | + |
| 7 | +class ImageService { |
| 8 | + async upload<T extends Readable & { name?: string; fileName?: string; filename?: string; path?: string | Buffer }>( |
| 9 | + file: T |
| 10 | + ): Promise<string> { |
| 11 | + // eslint-disable-next-line @typescript-eslint/naming-convention |
| 12 | + const FormData = (await import('form-data')).default |
| 13 | + const form = new FormData() |
| 14 | + const { name, fileName, filename, path: _path } = file |
| 15 | + const finalName = path.basename(isString(_path) ? _path : fileName || filename || name || 'image.png') |
| 16 | + const ext = path.extname(finalName) |
| 17 | + const mime = await import('mime') |
| 18 | + const mimeType = mime.lookup(ext, 'image/png') |
| 19 | + form.append('image', file, { filename: finalName, contentType: mimeType }) |
| 20 | + const response = await httpClient.post(`${ExtConst.ApiBase.BLOG_BACKEND}/posts/body/images`, { |
| 21 | + body: form, |
| 22 | + }) |
| 23 | + |
| 24 | + return response.body |
| 25 | + } |
| 26 | + |
| 27 | + /** |
| 28 | + * Download the image from web |
| 29 | + * This will reject if failed to download |
| 30 | + * @param url The url of the web image |
| 31 | + * @param name The name that expected applied to the downloaded image |
| 32 | + * @returns The {@link Readable} stream |
| 33 | + */ |
| 34 | + async download(url: string, name?: string): Promise<Readable> { |
| 35 | + const response = await httpClient.get(url, { responseType: 'buffer' }) |
| 36 | + const contentType = response.headers['content-type'] ?? 'image/png' |
| 37 | + name = name ? 'image' : name |
| 38 | + const mime = await import('mime') |
| 39 | + |
| 40 | + return merge(Readable.from(response.body), { |
| 41 | + ...pick(response, 'httpVersion', 'headers'), |
| 42 | + path: `${name}.${mime.extension(contentType) ?? 'png'}`, |
| 43 | + }) |
| 44 | + } |
| 45 | +} |
| 46 | + |
| 47 | +export const imageService = new ImageService() |
0 commit comments