Upload file to s3 with POST

后端 未结 1 869
温柔的废话
温柔的废话 2020-12-28 21:16

I\'d like to upload a file to AWS S3 via the POST interface, but I fail to do so.

I\'ve already made it work with PUT and getSignedUrl, but unfortunatel

相关标签:
1条回答
  • 2020-12-28 22:05

    Finally it works. Here's the code in case anyone has the same problem.

    A few things to note:

    • Request or form-data libraries have a bug, one of them doesn't set the 'Content-Lenght' header. See issue https://github.com/request/request/issues/316
    • The order of the form fields are important, acl latel, it will fail.
    • There are different AWS protocols out there, you should check the ones available in your zone. In my case, I had to set signatureVersion to V4 even in the S3 constructor.

    I'm not proud of the code quality, but at last it works.

    const aws = require('aws-sdk');
    const fs = require('fs');
    const request = require('request');
    const config = require('./config');
    
    let s3;
    
    const init = () => {
        aws.config.update({
            signatureVersion: 'v4',
            region: 'eu-central-1',
            accessKeyId: config.aws.keyId,
            secretAccessKey: config.aws.keySecret
        });
    
        s3 = new aws.S3({signatureVersion: 'v4'});
    };
    
    const signFile = (filePath) => {
        return new Promise((resolve, reject) => {
            const params = {
                Bucket: config.aws.bucket,
                Fields: {
                    key: filePath
                },
                Expires: config.aws.expire,
                Conditions: [
                    ['content-length-range', 0, 10000000], // 10 Mb
                    {'acl': 'public-read'}
                ]
            };
            s3.createPresignedPost(params, (err, data) => {
                resolve(data);
            });
        });
    };
    
    const sendFile = (filePath, payload) => {
        const fetch = require('node-fetch');
        const FormData = require('form-data');
    
        const form = new FormData();
        form.append('acl', 'public-read');
        for(const field in payload.fields) {
            form.append(field, payload.fields[field]);
        }
        form.append('file', fs.createReadStream(__dirname + `/${filePath}`));
        form.getLength((err, length) => {
            console.log(`Length: ${length}`);
            fetch(payload.url, {
                method: 'POST',
                body: form,
                headers: {
                    'Content-Type': false,
                    'Content-Length': length
                }
            })
            .then((response) => {
                console.log(response.ok);
                console.log(response.status);
                console.log(response.statusText);
                return response.text();
            })
            .then((payload) => {
                console.log(payload);
                console.log(form.getHeaders());
            })
            .catch((err) => console.log(`Error: ${err}`));
        });
    
    };
    
    
    init();
    
    const file = 'test.pdf';
    const filePath = `files/new/${file}`;
    signFile(filePath)
    .then((payload) => { sendFile(file, payload); });
    
    0 讨论(0)
提交回复
热议问题