no stream

This commit is contained in:
tamaina 2023-01-25 14:56:37 +00:00
parent a0b3bb2117
commit 636f9192fc
1 changed files with 13 additions and 24 deletions

View File

@ -1,4 +1,5 @@
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import { readFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path'; import { dirname } from 'node:path';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
@ -12,7 +13,7 @@ import { FILE_TYPE_BROWSERSAFE } from '@/const.js';
import { StatusError } from '@/misc/status-error.js'; import { StatusError } from '@/misc/status-error.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { DownloadService } from '@/core/DownloadService.js'; import { DownloadService } from '@/core/DownloadService.js';
import { IImageStreamable, ImageProcessingService, webpDefault } from '@/core/ImageProcessingService.js'; import { IImage, ImageProcessingService, webpDefault } from '@/core/ImageProcessingService.js';
import { VideoProcessingService } from '@/core/VideoProcessingService.js'; import { VideoProcessingService } from '@/core/VideoProcessingService.js';
import { InternalStorageService } from '@/core/InternalStorageService.js'; import { InternalStorageService } from '@/core/InternalStorageService.js';
import { contentDisposition } from '@/misc/content-disposition.js'; import { contentDisposition } from '@/misc/content-disposition.js';
@ -138,7 +139,7 @@ export class FileServerService {
const convertFile = async () => { const convertFile = async () => {
if (file.fileRole === 'thumbnail') { if (file.fileRole === 'thumbnail') {
if (['image/jpeg', 'image/webp', 'image/avif', 'image/png', 'image/svg+xml'].includes(file.mime)) { if (['image/jpeg', 'image/webp', 'image/avif', 'image/png', 'image/svg+xml'].includes(file.mime)) {
return this.imageProcessingService.convertToWebpStream( return await this.imageProcessingService.convertToWebp(
file.path, file.path,
498, 498,
280 280
@ -150,7 +151,7 @@ export class FileServerService {
if (file.fileRole === 'webpublic') { if (file.fileRole === 'webpublic') {
if (['image/svg+xml'].includes(file.mime)) { if (['image/svg+xml'].includes(file.mime)) {
return this.imageProcessingService.convertToWebpStream( return await this.imageProcessingService.convertToWebp(
file.path, file.path,
2048, 2048,
2048, 2048,
@ -160,7 +161,7 @@ export class FileServerService {
} }
return { return {
data: fs.createReadStream(file.path), data: await readFile(file.path),
ext: file.ext, ext: file.ext,
type: file.mime, type: file.mime,
}; };
@ -168,11 +169,6 @@ export class FileServerService {
const image = await convertFile(); const image = await convertFile();
if (typeof image.data === 'object' && 'pipe' in image.data && typeof image.data.pipe === 'function') {
image.data.on('end', file.cleanup);
image.data.on('close', file.cleanup);
}
reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(image.type) ? image.type : 'application/octet-stream'); reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(image.type) ? image.type : 'application/octet-stream');
reply.header('Cache-Control', 'max-age=31536000, immutable'); reply.header('Cache-Control', 'max-age=31536000, immutable');
return image.data; return image.data;
@ -196,9 +192,8 @@ export class FileServerService {
reply.header('Content-Disposition', contentDisposition('inline', file.file.name)); reply.header('Content-Disposition', contentDisposition('inline', file.file.name));
return stream; return stream;
} }
} catch (e) { } finally {
if ('cleanup' in file) file.cleanup(); if ('cleanup' in file) file.cleanup();
throw e;
} }
} }
@ -229,11 +224,11 @@ export class FileServerService {
const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image'); const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image');
const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image'); const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image');
let image: IImageStreamable | null = null; let image: IImage | null = null;
if ('emoji' in request.query && isConvertibleImage) { if ('emoji' in request.query && isConvertibleImage) {
if (!isAnimationConvertibleImage && !('static' in request.query)) { if (!isAnimationConvertibleImage && !('static' in request.query)) {
image = { image = {
data: fs.createReadStream(file.path), data: await readFile(file.path),
ext: file.ext, ext: file.ext,
type: file.mime, type: file.mime,
}; };
@ -252,9 +247,9 @@ export class FileServerService {
}; };
} }
} else if ('static' in request.query && isConvertibleImage) { } else if ('static' in request.query && isConvertibleImage) {
image = this.imageProcessingService.convertToWebpStream(file.path, 498, 280); image = await this.imageProcessingService.convertToWebp(file.path, 498, 280);
} else if ('preview' in request.query && isConvertibleImage) { } else if ('preview' in request.query && isConvertibleImage) {
image = this.imageProcessingService.convertToWebpStream(file.path, 200, 200); image = await this.imageProcessingService.convertToWebp(file.path, 200, 200);
} else if ('badge' in request.query) { } else if ('badge' in request.query) {
if (!isConvertibleImage) { if (!isConvertibleImage) {
// 画像でないなら404でお茶を濁す // 画像でないなら404でお茶を濁す
@ -291,30 +286,24 @@ export class FileServerService {
type: 'image/png', type: 'image/png',
}; };
} else if (file.mime === 'image/svg+xml') { } else if (file.mime === 'image/svg+xml') {
image = this.imageProcessingService.convertToWebpStream(file.path, 2048, 2048); image = await this.imageProcessingService.convertToWebp(file.path, 2048, 2048);
} else if (!file.mime.startsWith('image/') || !FILE_TYPE_BROWSERSAFE.includes(file.mime)) { } else if (!file.mime.startsWith('image/') || !FILE_TYPE_BROWSERSAFE.includes(file.mime)) {
throw new StatusError('Rejected type', 403, 'Rejected type'); throw new StatusError('Rejected type', 403, 'Rejected type');
} }
if (!image) { if (!image) {
image = { image = {
data: fs.createReadStream(file.path), data: await readFile(file.path),
ext: file.ext, ext: file.ext,
type: file.mime, type: file.mime,
}; };
} }
if (typeof image.data === 'object' && 'pipe' in image.data && typeof image.data.pipe === 'function' && 'cleanup' in file) {
image.data.on('end', file.cleanup);
image.data.on('close', file.cleanup);
}
reply.header('Content-Type', image.type); reply.header('Content-Type', image.type);
reply.header('Cache-Control', 'max-age=31536000, immutable'); reply.header('Cache-Control', 'max-age=31536000, immutable');
return image.data; return image.data;
} catch (e) { } finally {
if ('cleanup' in file) file.cleanup(); if ('cleanup' in file) file.cleanup();
throw e;
} }
} }