简体   繁体   中英

Upload a pdf file to Google Cloud Storage with Node.js

I am new to uploading to Google Cloud Buckets and am having issues uploading a pdf document to a Google Cloud Bucket. The aim is to use PDFKit to create a pdf document, send that up to the Bucket, and then respond with the url of the file that can then be used on the client side to download the file.

Currently, a file is being uploaded to the bucket, but is saying its damaged when trying to open it, as is the file that downloads from the frontend.

This is the create method i currently have:

const PDFDocument = require('pdfkit');
const storage = require('./storage');

async function create(req, res) {
  const doc_name = `invoice_${req.body.id}.pdf`;
  const doc = new PDFDocument({
    compress: false,
  });
  doc.fontSize(12);
  doc.text('PDFKit is simple', 10, 30, {
    align: 'center',
    width: 200,
  });
  doc.end();
  const fileId = await storage.upload(doc, req.account.id);
  const url = await storage.getSignedURL(fileId, doc_name);

  res.send(JSON.stringify({ doc: { url: url[0], name: doc_name } }));
}

module.exports = create;

This is using the following to upload the file:

const { Storage } = require('@google-cloud/storage');
const moment = require('moment');
const stream = require('stream');
const uuidv4 = require('uuid/v4');

const storage = new Storage();
const bucket = storage.bucket(process.env.GOOGLE_STORAGE_BUCKET);
const fileSuffix = 'pdf';

const getBucketFile = fileName => bucket.file(`${fileName}.${fileSuffix}`);
const getSignedURL = (fileName, name) => {
  const file = getBucketFile(fileName);
  const config = {
    action: 'read',
    expires: moment()
      .add(6, 'd')
      .format('MM-DD-YYYY'),
    responseDisposition: `inline; filename=${name}`,
  };
  return file.getSignedUrl(config);
};

const upload = (data, prefix) => new Promise((resolve, reject) => {
  const uuid = `${prefix}/${uuidv4()}`;
  const stream = require('stream');
  const bufferStream = new stream.PassThrough();
  bufferStream.end(Buffer.from(data.toString(), 'base64'));
  const file = getBucketFile(uuid);
  bufferStream
    .pipe(file.createWriteStream())
    .on('error', err => reject(err))
    .on('finish', () => resolve(uuid));
});

module.exports = {
  getSignedURL,
  upload,
};

I've seen others using firebase but am struggling to translate to google cloud. Any help will be massively appreciated!

I have modified you upload to a version that works for me:

const { Storage } = require("@google-cloud/storage");
const { v4: uuidv4 } = require("uuid");
const bucketName = require("../config/endpoints").BUCKETNAME;

const storage = new Storage();

const bucket = storage.bucket(bucketName);
const fileSuffix = "pdf";

const getBucketFile = fileName => 
   bucket.file(`${fileName}.${fileSuffix}`);
const getSignedURL = async fileName => {
  let validTime = new Date();
  validTime.setHours(validTime.getHours() + 1);
  const config = {
    version: "v4",
    action: "read",
    expires: validTime
  };

  const signedUrl = await storage
     .bucket(bucketName)
     .file(fileName)
     .getSignedUrl(config);
  return signedUrl;
};

const upload = (data) =>
   new Promise((resolve, reject) => {
   const uuid = `pdf/${uuidv4()}`;
   const file = getBucketFile(uuid);
   const stream = file.createWriteStream({
     metadata: {
       "Content-Type": "application/pdf",
       "content-Disposition": `attachment; filename=${uuid}.pdf`
     },
     resumable: false
   });
   stream.on("error", err => {
      reject(error);
   }); 

   stream.on("finish", () => {
     resolve(uuid);
   });

   stream.end(Buffer.from(data.toString(), "binary"));
 });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM