使用Node.js AWS SDK将生成的PDF上传到AWS S3

18

我正在使用pdfkit生成包含自定义内容的pdf文件,然后将其发送到AWS S3存储桶。

如果我将整个文件生成并上传,则可以正常工作,但是,如果我想将生成的文件流式传输,例如作为八位字节流,我找不到任何相关的指针。

我正在寻找一个基于Node.js的解决方案(或建议)。


你尝试使用过 request 模块吗?你应该可以将 doc 管道传输到 request - edin-m
好的,我已经找到了解决方案。处理的方法是使用S3 API的上传(upload)而不是putObject。 因此,您可以将可读流用作s3上传参数的正文(body)。 - Shivendra Soni
欢迎来到stackoverflow。如果您有用的答案,请发布它。 - edin-m
已将其添加为答案。请告诉我是否需要添加更多内容。 - Shivendra Soni
4个回答

32

我会尽力准确表达。我不会详细介绍pdfKit的 nodejs sdk 的用法。

如果你想将生成的 PDF 文件作为文件保存。

var PDFDocument = require('pdfkit');

// Create a document
doc = new PDFDocument();

// Pipe it's output somewhere, like to a file or HTTP response
doc.pipe(fs.createWriteStream('output.pdf'));
doc.text('Whatever content goes here');
doc.end();
var params = {
  key : fileName,
  body : './output.pdf',
  bucket : 'bucketName',
  contentType : 'application/pdf'
}

s3.putObject(params, function(err, response) {

});

然而,如果您想将其流式传输(在问题的上下文中说S3存储桶),则值得记住每个pdfkit实例都是可读流。

S3希望获得一个文件、缓冲区或可读流。

var doc = new PDFDocument();

// Pipe it's output somewhere, like to a file or HTTP response
doc.text("Text for your PDF");
doc.end();

var params = {
  key : fileName,
  body : doc,
  bucket : 'bucketName',
  contentType : 'application/pdf'
}

//notice use of the upload function, not the putObject function
s3.upload(params, function(err, response) {

});

你正在使用 aws-sdk 或其他模块吗?现在尝试使用 knox 并使用 putStream 来完成此操作。我的文件没有保存在文件系统中,只是流式传输到了 s3。 - Nigel Earle
是的,我正在使用aws-sdk。 - Shivendra Soni
1
无法确定 [object PDFDocument] 的长度:请改用 s3.upload():https://dev59.com/1Irda4cB1Zd3GeqPRdS4 - ricka
@ShivendraSoni:我们可以在doc.text()中绑定HTML内容吗? - shiva
1
写入磁盘不能保证在开始上传时已经完成。使用上述方法可能会导致文件损坏。请参见https://github.com/foliojs/pdfkit/issues/265。 - Ioannis Tsiokos
显示剩余3条评论

5

我尝试了这个方法并且成功了。我创建了一个readFileSync然后上传到S3中。我还使用了"writeStream.on('finish'"来确保在上传之前完全创建pdf文件,否则它会上传部分文件。

const PDFDocument = require('pdfkit');
const fs = require('fs');
const AWS = require('aws-sdk');
const path = require('path')

async function createPDF() {


const doc = new PDFDocument({size: 'A4'});
let writeStream = fs.createWriteStream('./output.pdf')
doc.pipe(writeStream);


// Finalize PDF file
doc.end();

writeStream.on('finish', function () {
    var appDir = path.dirname(require.main.filename);
    const fileContent = fs.readFileSync(appDir + '/output.pdf');
    var params = {
        Key : 'filName',
        Body : fileContent,
        Bucket : process.env.AWS_BUCKET,
        ContentType : 'application/pdf',
        ACL: "public-read"
      }
      
    const s3 = new AWS.S3({
        accessKeyId: process.env.AWS_ACCESS_KEY,
        secretAccessKey: process.env.AWS_SECRET_KEY
    });
      //notice use of the upload function, not the putObject function
    s3.upload(params, function(err, response) {
        
    });
});

}


5
如果您正在使用 html-pdf 包和 aws-sdk,那么这很容易...
var pdf = require('html-pdf');
import aws from 'aws-sdk';
const s3 = new aws.S3();

pdf.create(html).toStream(function(err, stream){
  stream.pipe(fs.createWriteStream('foo.pdf'));
  const params = {
                Key: 'foo.pdf',
                Body: stream,
                Bucket: 'Bucket Name',
                ContentType: 'application/pdf',
            };
  s3.upload(params, (err, res) => {
                if (err) {
                    console.log(err, 'err');
                }
                console.log(res, 'res');
            });
});

stream.pipe 抛出错误 Error: ENOENT: no such file or directory, open './2020-2021/11761.pdf'] - Lalitesh Upadhyaya
这个文件夹中是否存在“2020-2021”?这段代码的主要目的是从HTML生成PDF文件并直接上传到S3。该文件不会存储在您的目录中。 - Subham kuswa

0

这是我如何使用Cypress将PDF文件上传到AWS S3的方法:

cy.readFile("cypress/fixtures/Document.pdf", "base64").then((fileBase64) => {
    const fileBlob = Cypress.Blob.base64StringToBlob(fileBase64, "application/pdf");
    uploadFileToS3(blob);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接