简体   繁体   English

使用 NodeJS 从 AWS S3 下载 pdf 文件

[英]Downloading a pdf file from AWS S3 using NodeJS

I'm trying to download a pdf file from S3, but everytime I download it to my local machine, I receive the error, "Error: Failed to load PDF".我正在尝试从 S3 下载 pdf 文件,但每次将其下载到本地计算机时,都会收到错误消息“错误:无法加载 PDF”。 It seems I am still downloading a blob instead of a file, but have tried everything and looked through too many stackoverflow solutions.看来我仍在下载 blob 而不是文件,但已经尝试了所有方法并查看了太多的 stackoverflow 解决方案。

Here is my backend code where the download function lives (sorry, it's still messy): backend --> middleware --> amazon.js这是我下载 function 所在的后端代码(对不起,它仍然很乱):后端 --> 中间件 --> amazon.js

const AWS = require('aws-sdk');
const fs = require('fs');
const uuid = require('uuid');
require('dotenv').config()
console.log("proccess", process.env.IAM_USER_KEY)
var dataUriToBuffer = require('data-uri-to-buffer');
const _path = require('path');
const { post } = require('../routes/user.data');
const { app } = require('firebase-admin');
const multer = require('multer');

var FileReader = require('filereader')
    , fileReader = new FileReader
    ;

AWS.config.update({
    accessKeyId: process.env.IAM_USER_KEY,
    secretAccessKey: process.env.IAM_USER_SECRET,
    region: 'us-east-1'
})

const s3 = new AWS.S3()

async function upload(req, res, next){
    let key = req.params.source+"/"+req.params.data.fields.id;

    // function to save the user uploaded file to "uploads" folder

    const uploadFile = (fileName) => {
        
        // Read content from the file
        const fileContent = fs.readFileSync(fileName);        
    
        // Setting up S3 upload parameters
        const params = {
            Bucket: process.env.BUCKET,
            Key: key, // File name you want to save as in S3
            Body: fileContent
        };
    
        // Uploading files to the bucket
        s3.upload(params, function(err, data) {
            if (err) {
                throw err;
            }
            console.log(`File uploaded successfully. ${data.Location}`);
        });
    };
    var filePath = _path.resolve(req.params.data.file.name);
    uploadFile(req.params.file_path)
}

async function download(req, res, next){
    let report_object = req.body.object_id
    report_object = report_object[0]
    let source = req.body.source

    let dir = _path.join(__dirname, '..', 'public')
    let fileName = `${source}.pdf`
    let filePath = _path.join(dir, fileName)

    let writeStream = fs.createWriteStream(filePath)

    var params = {
        Key: source+"/"+report_object,
        Bucket: process.env.BUCKET
    }
    const readStream = s3.getObject(params).createReadStream();
    
    // Error handling in read stream
    readStream.on("error", (e) => {
        console.error(e);
        reject(e);
    });
    
    readStream.pipe(writeStream);
    writeStream.on('finish', () => {
        res.download(dir + "/" + fileName)
    })
}

module.exports = { upload, download }

And here is my download function in the api interface that is found in the frontend and communicates with the backend:这是我在前端找到并与后端通信的api接口中的下载function:

import axios from 'axios';
import fs from 'fs'
import streamToBlob from 'stream-to-blob'


async function upload(data, user){
    data["user"] = user
    await axios({
        method: 'post', 
        url: 'http://localhost:3000/s3/upload', 
        data: data,
        headers: { "content-type": "multipart/form-data"},
    })
}

 function download(id, source){
    let data =  axios.post("http://localhost:3000/s3/download", {object_id: id, source: source}, { headers : {'Accept' : "application/pdf"}}).then( (res) => {
        let blob = new Blob([res.data], {type: 'application/pdf'})
        const link = document.createElement('a')
        link.href = URL.createObjectURL(blob)
        link.download = `${source}`
        link.click()
        setTimeout(function() {
            URL.revokeObjectURL(link.href)
        }, 60000)
        
        return
    })
}

export {upload, download}

I believe that the current download is a blob because I see that in the network tab of the dev inspect tools.我相信当前的下载是一个 blob,因为我在开发检查工具的网络选项卡中看到了它。

Thank you in advance for your help.预先感谢您的帮助。

Not sure what version of the AWS SDK you are using.不确定您使用的是什么版本的 AWS SDK。 With @aws-sdk/client-s3 , version 3.3.0 I was able to:使用@aws-sdk/client-s3版本3.3.0我能够:

import { S3 } from '@aws-sdk/client-s3'
const express = require('express')

const expressInstance = express()

const s3Client = new S3({
  region: '...',
  credentials: {
    accessKeyId: '...',
    secretAccessKey: '...'
  }
})

expressInstance.get('/durl', async (req, res) => {

  const object = await s3Client.getObject({
    Bucket: '...',
    Key: decodeURIComponent(req.query.k)
  }

  object.Body.pipe(res)

})

... with a simple front JS: ...用一个简单的前端JS:

const link = document.createElement('a')
link.href = '.../durl?k=my.pdf'
link.download = `my.pdf`
link.click()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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