处理文件 在文件里除了文件数据本身还有些额外的数据,比如音频,视频文件里可能会包含内容的作者、专辑、版权等信息,在照片文件里可能会包含设备、型号、大小、镜头、日期等等,设计一个接口方便客户端可以调取这些数据。
读取图像文件的附加信息 安装 jimp
file.middleware.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import { Request, Response, NextFunction } from "express"; import multer from "multer"; import Jimp from "jimp"; /** * 创建一个multer */ const fileUpload = multer({ dest: "uploads/", }); /** * 文件拦截器 */ export const fileInterceptor = fileUpload.single("file"); /** * 文件处理器 */ export const fileProcessor = async ( request: Request, response: Response, next: NextFunction ) => { //文件路径 const { path } = request.file; let image: Jimp; try { //读取图像文件 image = await Jimp.read(path); } catch (error) { return next(error); } console.log(image); //下一步 next(); };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import express from "express"; import { authGuard } from "../auth/auth.middleware"; import * as fileController from "./file.controller"; import { fileInterceptor, fileProcessor } from "./file.middleware"; const router = express.Router(); /** * 上传文件 */ router.post( "/files", authGuard, fileInterceptor, fileProcessor, fileController.store ); /** * 文件服务 */ router.get("/files/:fileId/serve", fileController.serve); /** * 导出路由 */ export default router;
存储图像的附加信息 设置类型 types/express.d.ts:
1 2 3 4 5 6 7 8 9 10 import { TokenPayload } from "../src/auth/auto.interface"; declare global { namespace Express { export interface Request { user: TokenPayload; fileMetaData: { width?: number; height?: number; metadata?: {} }; } } }
file.middleware.ts 中加入:
1 2 3 4 5 6 // 在请求中添加文件数据 request.fileMetaData = { width: imageSize.width, height: imageSize.height, metadata: JSON.stringify(tags), };
file.controller.ts 中加入:
1 2 3 4 5 6 7 //保存文件信息 const data = await createFile({ ...fileInfo, userId, postId, ...request.fileMetaData, });
定义调取图像信息的接口 file.controller.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /** * 文件信息 */ export const metadata = async ( request: Request, response: Response, next: NextFunction ) => { //文件ID const { fileId } = request.params; try { //查询文件数据 const file = await findFileById(parseInt(fileId, 10)); //准备响应数据 const data = _.pick(file, ["id", "size", "width", "height", "metadata"]); //做出响应 response.send(data); } catch (error) { next(error); } };
file.router.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import express from "express"; import { authGuard } from "../auth/auth.middleware"; import * as fileController from "./file.controller"; import { fileInterceptor, fileProcessor } from "./file.middleware"; const router = express.Router(); /** * 上传文件 */ router.post( "/files", authGuard, fileInterceptor, fileProcessor, fileController.store ); /** * 文件服务 */ router.get("/files/:fileId/serve", fileController.serve); /** * 文件信息 */ router.get("/files/:fileId/metadata", fileController.metadata); /** * 导出路由 */ export default router;
调整图像尺寸 file.service.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import path from "path"; import Jimp from "jimp"; import { connection } from "../app/database/mysql"; import { FileModel } from "./file.model"; /** * 调整图像尺寸 */ export const imageResizer = async (image: Jimp, file: Express.Multer.File) => { //图像尺寸 const { imageSize } = image["_exif"]; //文件路径 const filePath = path.join(file.destination, "resized", file.filename); // 大尺寸 if (imageSize.width > 1280) { image .resize(1280, Jimp.AUTO) .quality(85) .write(`${filePath}-large`); } // 中等尺寸 if (imageSize.width > 640) { image .resize(640, Jimp.AUTO) .quality(85) .write(`${filePath}-medium`); } // 缩略图 if (imageSize.width > 320) { image .resize(320, Jimp.AUTO) .quality(85) .write(`${filePath}-thumbnail`); } };
file.middleware.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import { Request, Response, NextFunction } from "express"; import multer from "multer"; import Jimp from "jimp"; import { imageResizer } from "./file.service"; /** * 文件处理器 */ export const fileProcessor = async ( request: Request, response: Response, next: NextFunction ) => { //文件路径 const { path } = request.file; let image: Jimp; try { //读取图像文件 image = await Jimp.read(path); } catch (error) { return next(error); } //准备文件数据 const { imageSize, tags } = image["_exif"]; // 在请求中添加文件数据 request.fileMetaData = { width: imageSize.width, height: imageSize.height, metadata: JSON.stringify(tags), }; //调整图像尺寸 imageResizer(image, request.file); //下一步 next(); };