使用ReadableStreams通过Nodemailer发送S3中托管的电子邮件附件

ejk8hzay  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(113)

我正在尝试使用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.
ldxq2e6h

ldxq2e6h1#

这是S3 SDK的一个已知问题(查看这个GitHub issue),它将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
}

相关问题