我正在尝试使用 JS AWS SDK v3 使用 Nodemailer 发送包含 S3 中托管的附件的电子邮件。 Nodemailer 文档显示了使用读取文件生成的读取流发送附件的示例:
{ // stream as an attachment
filename: 'text4.txt',
content: fs.createReadStream('file.txt')
},
我可以在 S3 中为我的附件创建一个
ReadableStream
,如下所示:
const s3Stream = await s3Client
.send(/* ... */)
.then((response) => {
// ...
return response.Body.transformToWebStream() // returns Promise<ReadableStream>
})
.catch(/* ... */)
如果我尝试将
s3Stream
直接传递到 Nodemailer 附件的 content
字段,我会收到错误:Type 'ReadableStream' is not assignable to type 'string | Readable | Buffer | undefined
。
Readable
类有一个静态方法fromWeb
。调用 Readable.fromWeb(s3Stream)
会给出以下信息:
Argument of type 'ReadableStream' is not assignable to parameter of type 'ReadableStream<any>'.
Type 'ReadableStream' is missing the following properties from type 'ReadableStream<any>': locked, cancel, getReader, pipeThrough, and 4 more.
Readable
对象有一个方法 wrap
:
new Readable().wrap(s3Stream)
尝试此操作会导致以下错误:
Argument of type 'ReadableStream' is not assignable to parameter of type 'NodeJS.ReadableStream'.
Type 'ReadableStream' is missing the following properties from type 'ReadableStream': readable, read, setEncoding, pause, and 22 more.
这是 S3 SDK 的一个已知问题(查看此 GitHub 问题 ),它显示
response.Body
作为浏览器 (ReadableStream
) 和 Node.js (Readable
) 类型的交集,而在运行时返回根据您运行它的平台确定值的类型。
因此,如果您确定您的代码只能在 Node.js 中运行,您只需进行类型转换:
import { Readable } from 'node:stream';
(res.Body as Readable)?.pipe(...);
或者更好的是添加一个类型保护以确保:
import { Readable } from 'node:stream';
if(isReadable(res.Body)) {
res.Body.pipe(fs.createWriteStream('/Users/edgar/Projects/Petabox/scripts/file2.txt'));
} else {
throw new TypeError('res.Body is not a readable stream');
}
function isReadable(value: unknown): value is Readable {
return value instanceof Readable
}