使用fs.createReadStream()获取Content-Type?解决TS2339错误
问题:使用fs.createReadStream()时如何获取文件的Content-Type?
我把原本用fs.readFile()的代码改成fs.createReadStream()后,写了这段代码:
const filePath = "/home/a/bars/img1.png"; const uploadParams: { Bucket: string; Key: string; Body: string | ReadStream; ContentType: any; ACL: string } = { Bucket: bucketName, Key: '', Body: '', ContentType: null, ACL: 'public-read', }; const fileStream = fs.createReadStream(filePath); fileStream.on('error', function (err) { console.log('File Error', err); }); uploadParams.Body = fileStream; uploadParams.Key = path.basename(filePath); uploadParams.ContentType = fileStream.mimetype; // 此处报错 uploadParams.ACL = 'public-read';
执行时遇到TypeScript错误:
Property 'mimetype' does not exist on type 'ReadStream'.ts(2339)
请问用fs.createReadStream()时该怎么获取文件的Content-Type?
解决方案
fs.ReadStream本身没有mimetype属性,你可以通过以下几种方式获取文件的Content-Type:
1. 通过文件扩展名推断
利用path模块获取文件扩展名,结合Node.js内置的mime模块(v14.17.0+内置)映射对应MIME类型:
import { createReadStream } from 'fs'; import { basename, extname } from 'path'; import { lookup } from 'mime'; const filePath = "/home/a/bars/img1.png"; const fileExt = extname(filePath); const contentType = lookup(fileExt) || 'application/octet-stream'; const uploadParams = { Bucket: bucketName, Key: basename(filePath), Body: createReadStream(filePath), ContentType: contentType, ACL: 'public-read', };
如果你的Node.js版本较低,也可以手动维护扩展名与MIME类型的映射表,比如:
const mimeMap: Record<string, string> = { '.png': 'image/png', '.jpg': 'image/jpeg', '.txt': 'text/plain' }; const contentType = mimeMap[fileExt] || 'application/octet-stream';
2. 通过文件头签名(Magic Number)判断
如果文件没有扩展名或扩展名不准确,可以读取文件的前几个字节,根据文件签名推断真实MIME类型。你可以用第三方库file-type简化这个过程:
import { createReadStream } from 'fs'; import { basename } from 'path'; import { fileTypeFromFile } from 'file-type'; async function getUploadParams() { const filePath = "/home/a/bars/img1.png"; const fileType = await fileTypeFromFile(filePath); const contentType = fileType?.mime || 'application/octet-stream'; const uploadParams = { Bucket: bucketName, Key: basename(filePath), Body: createReadStream(filePath), ContentType: contentType, ACL: 'public-read', }; return uploadParams; }
这种方法是异步的,需要在async函数中调用。
3. 手动读取文件头实现
如果不想依赖第三方库,也可以自己读取文件前几个字节,对照文件签名表判断MIME类型。比如PNG文件的开头字节是89 50 4E 47,对应image/png:
import { createReadStream, readFileSync } from 'fs'; import { basename } from 'path'; function getContentType(filePath: string): string { const buffer = readFileSync(filePath, { byteLength: 8 }); // 检查PNG签名 if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && buffer[3] === 0x47) { return 'image/png'; } // 可添加更多文件类型的签名判断 return 'application/octet-stream'; } const filePath = "/home/a/bars/img1.png"; const contentType = getContentType(filePath); const uploadParams = { Bucket: bucketName, Key: basename(filePath), Body: createReadStream(filePath), ContentType: contentType, ACL: 'public-read', };
内容的提问来源于stack exchange,提问作者best_of_man
相关产品推荐
相关产品推荐

