【问题标题】:Upload pdf generated to AWS S3 using nodejs aws sdk使用 nodejs aws sdk 将生成的 pdf 上传到 AWS S3
【发布时间】:2016-03-19 08:27:31
【问题描述】:

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

虽然如果我将文件作为一个整体生成并上传它可以完美地工作,但是,如果我想将生成的文件作为八位字节流进行流式传输,我无法找到任何相关的指针。

我正在寻找 nodejs 解决方案(或建议)。

【问题讨论】:

  • 您是否尝试过使用request 模块?您应该能够将doc 传送到request
  • 好的,我找到了解决方案。这样做的方法是使用上传而不是 putObject 和 s3 api。因此,您可以使用可读流作为 s3 上传参数的主体。
  • 欢迎来到stackoverflow。发布答案,因为有人可能会觉得它有用。
  • 将其添加为答案。请告诉我是否还有什么需要补充的。

标签: javascript node.js amazon-s3 aws-sdk node-pdfkit


【解决方案1】:

我会尽量做到准确。我不会详细介绍 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。
  • 是的,我正在使用 aws-sdk
  • '无法确定 [object PDFDocument] 的长度':使用 s3.upload() 代替:stackoverflow.com/questions/30227352/…
  • @ShivendraSoni:我们可以在 doc.text() 中绑定 html 内容吗?
  • 不保证在您开始上传时已完成写入磁盘。使用上述方法可能会导致文件损坏。见github.com/foliojs/pdfkit/issues/265
【解决方案2】:

如果你使用的是 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']
  • 2020-2021 这个文件夹存在吗?这个代码块的主要目的是从html生成pdf文件并直接上传到s3。该文件不会存储在您的目录中。
【解决方案3】:

试过这个并且奏效了。我创建了一个 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) {
        
    });
});

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    相关资源
    最近更新 更多