Programing

NodeJS를 사용하여 Amazon S3에 파일 업로드

lottogame 2021. 1. 7. 07:34
반응형

NodeJS를 사용하여 Amazon S3에 파일 업로드


S3 버킷에 파일을 업로드하는 동안 문제가 발생했습니다. 내 파일 매개 변수가 적절하지 않은 것 외에는 모든 것이 작동합니다. Amazon S3 SDK를 사용하여 nodejs에서 s3로 업로드하고 있습니다.

다음은 내 경로 설정입니다.

var multiparty = require('connect-multiparty'),
    multipartyMiddleware = multiparty();
app.route('/api/items/upload').post(multipartyMiddleware, items.upload);

이것은 items.upload () 함수입니다 :

exports.upload = function(req, res) {
    var file = req.files.file;
    var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}});
    s3bucket.createBucket(function() {
        var params = {
            Key: file.name,
            Body: file
        };
        s3bucket.upload(params, function(err, data) {
            console.log("PRINT FILE:", file);
            if (err) {
                console.log('ERROR MSG: ', err);
            } else {
                console.log('Successfully uploaded data');
            }
        });
    });
};

Bodyparam을 문자열로 설정하면 "hello"정상적으로 작동합니다. 에 따르면 문서 , BodyPARAM가 수행해야합니다 (버퍼, 형식화 된 배열, 물방울, 문자열, ReadableStream) Object 데이터를. 그러나 파일 객체 업로드는 다음 오류 메시지와 함께 실패합니다.

[Error: Unsupported body payload object]

이것은 파일 객체입니다.

{ fieldName: 'file',
  originalFilename: 'second_fnp.png',
  path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png',
  headers: 
   { 'content-disposition': 'form-data; name="file"; filename="second_fnp.png"',
     'content-type': 'image/png' },
  ws: 
   { _writableState: 
      { highWaterMark: 16384,
        objectMode: false,
        needDrain: true,
        ending: true,
        ended: true,
        finished: true,
        decodeStrings: true,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function],
        writecb: null,
        writelen: 0,
        buffer: [],
        errorEmitted: false },
     writable: true,
     domain: null,
     _events: { error: [Object], close: [Object] },
     _maxListeners: 10,
     path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png',
     fd: null,
     flags: 'w',
     mode: 438,
     start: undefined,
     pos: undefined,
     bytesWritten: 261937,
     closed: true },
  size: 261937,
  name: 'second_fnp.png',
  type: 'image/png' }

어떤 도움이라도 대단히 감사하겠습니다!


그래서 여기에 몇 가지 문제가있는 것 같습니다. 귀하의 게시물에 따르면 connect-multiparty미들웨어를 사용하여 파일 업로드를 지원하려는 것 같습니다 . 이 미들웨어가하는 일은 업로드 된 파일을 가져 와서 로컬 파일 시스템에 쓴 다음 req.files업로드 된 파일 로 설정 하는 것입니다.

경로 구성은 괜찮아 보이지만 문제는 items.upload()기능에 있는 것 같습니다. 특히이 부분에서 :

var params = {
  Key: file.name,
  Body: file
};

내 대답의 시작 부분에서 언급했듯이 connect-multiparty파일을 로컬 파일 시스템에 기록하므로 파일을 열고 읽은 다음 업로드 한 다음 로컬 파일 시스템에서 삭제해야합니다.

즉, 메서드를 다음과 같이 업데이트 할 수 있습니다.

var fs = require('fs');
exports.upload = function (req, res) {
    var file = req.files.file;
    fs.readFile(file.path, function (err, data) {
        if (err) throw err; // Something went wrong!
        var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}});
        s3bucket.createBucket(function () {
            var params = {
                Key: file.originalFilename, //file.name doesn't exist as a property
                Body: data
            };
            s3bucket.upload(params, function (err, data) {
                // Whether there is an error or not, delete the temp file
                fs.unlink(file.path, function (err) {
                    if (err) {
                        console.error(err);
                    }
                    console.log('Temp File Delete');
                });

                console.log("PRINT FILE:", file);
                if (err) {
                    console.log('ERROR MSG: ', err);
                    res.status(500).send(err);
                } else {
                    console.log('Successfully uploaded data');
                    res.status(200).end();
                }
            });
        });
    });
};

이것이하는 일은 로컬 파일 시스템에서 업로드 된 파일을 읽어서 S3에 업로드 한 다음 임시 파일을 삭제하고 응답을 보내는 것입니다.

이 접근 방식에는 몇 가지 문제가 있습니다. 첫째, 큰 파일의 경우 쓰기 전에 전체 파일을로드하게되므로 가능한 한 효율적이지 않습니다. 둘째,이 프로세스는 대용량 파일에 대한 멀티 파트 업로드를 지원하지 않습니다 (멀티 파트 업로드를 수행하기 전에 컷오프가 5Mb라고 생각합니다).

대신 내가 제안하는 것은 Node.JS 의 네이티브 FS 와 유사한 인터페이스를 제공 하지만 멀티 파트 업로드 및 S3 API와 같은 일부 세부 정보를 추상화 하는 S3FS 라는 모듈을 사용하는 것 입니다. (또한 재귀 메서드와 같은 추가 기능을 추가합니다).

S3FS 라이브러리 를 가져 오면 코드는 다음과 같습니다.

var fs = require('fs'),
    S3FS = require('s3fs'),
    s3fsImpl = new S3FS('mybucketname', {
        accessKeyId: XXXXXXXXXXX,
        secretAccessKey: XXXXXXXXXXXXXXXXX
    });

// Create our bucket if it doesn't exist
s3fsImpl.create();

exports.upload = function (req, res) {
    var file = req.files.file;
    var stream = fs.createReadStream(file.path);
    return s3fsImpl.writeFile(file.originalFilename, stream).then(function () {
        fs.unlink(file.path, function (err) {
            if (err) {
                console.error(err);
            }
        });
        res.status(200).end();
    });
};

이렇게하면 제공된 버킷 및 AWS 자격 증명에 대한 모듈을 인스턴스화 한 다음 버킷이없는 경우 생성합니다. 그런 다음 파일 업로드 요청이 들어 오면 파일에 대한 스트림을 열고이를 사용하여 S3에 지정된 경로에 파일을 씁니다. 이렇게하면 백그라운드에서 (필요한 경우) 멀티 파트 업로드 조각을 처리하고 스트림을 통해 수행 할 수 있으므로 업로드를 시작하기 전에 전체 파일을 읽을 때까지 기다릴 필요가 없습니다.

원하는 경우 코드를 Promises의 콜백으로 변경할 수 있습니다 . 또는 이벤트 리스너와 함께 pipe () 메서드를 사용하여 종료 / 오류를 확인합니다.

몇 가지 추가 방법을 찾고 있다면 s3fs에 대한 설명서를 확인하고 몇 가지 추가 방법을 찾거나 문제가있는 경우 언제든지 문제를 열어보십시오.


다음이 작동하는 해결 책임을 알았습니다. :

npm install aws-sdk


aws-sdk를 설치했으면 다음 코드를 사용하여 값을 필요한 위치로 바꿉니다.

var AWS = require('aws-sdk');
var fs =  require('fs');

var s3 = new AWS.S3();

// Bucket names must be unique across all S3 users

var myBucket = 'njera';

var myKey = 'jpeg';
//for text file
//fs.readFile('demo.txt', function (err, data) {
//for Video file
//fs.readFile('demo.avi', function (err, data) {
//for image file                
fs.readFile('demo.jpg', function (err, data) {
  if (err) { throw err; }



     params = {Bucket: myBucket, Key: myKey, Body: data };

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

         if (err) {

             console.log(err)

         } else {

             console.log("Successfully uploaded data to myBucket/myKey");

         }

      });

});

참고 문헌을 찾는 경우를 대비하여 주제에 대한 전체 자습서를 찾았습니다.


node.js를 사용하여 Amazon S3에서 파일 (텍스트 / 이미지 / 비디오)을 업로드하는 방법


또는 약속 사용 :

const AWS = require('aws-sdk');
AWS.config.update({
    accessKeyId: 'accessKeyId',
    secretAccessKey: 'secretAccessKey',
    region: 'region'
});

let params = {
    Bucket: "yourBucketName",
    Key: 'someUniqueKey',
    Body: 'someFile'
};
try {
    let uploadPromise = await new AWS.S3().putObject(params).promise();
    console.log("Successfully uploaded data to bucket");
} catch (e) {
    console.log("Error uploading data: ", e);
}

AWS s3에 파일을 업로드하고 파일 액세스에 대한 응답으로 URL을 전송합니다.

Multer는 주로 파일 업로드에 사용되는 multipart / form-data 처리를위한 node.js 미들웨어입니다. 최대 효율을 위해 busboy 위에 작성되었습니다. 여기 에서이 npm 모듈을 확인 하십시오 .

When you are sending the request, make sure the headers, have Content-Type is multipart/form-data. We are sending the file location in the response, which will give the url, but if you want to access that url, make the bucket public or else you will not be able to access it.

upload.router.js

const express = require('express');
const router = express.Router();
const AWS = require('aws-sdk');
const multer = require('multer');
const storage = multer.memoryStorage()
const upload = multer({storage: storage});

const s3Client = new AWS.S3({
    accessKeyId: 'your_access_key_id',
    secretAccessKey: 'your_secret_access_id',
    region :'ur region'
});

const uploadParams = {
         Bucket: 'ur_bucket_name', 
         Key: '', // pass key
         Body: null, // pass file body
};


router.post('/api/file/upload', upload.single("file"),(req,res) => {
    const params = uploadParams;

    uploadParams.Key = req.file.originalname;
    uploadParams.Body = req.file.buffer;

    s3Client.upload(params, (err, data) => {
        if (err) {
            res.status(500).json({error:"Error -> " + err});
        }
        res.json({message: 'File uploaded successfully','filename': 
        req.file.originalname, 'location': data.Location});
    });
});

module.exports = router;

app.js

const express = require('express');
const app = express();

const router = require('./app/routers/upload.router.js');
app.use('/', router);

// Create a Server
  const server = app.listen(8080, () => {
  console.log("App listening at 8080"); 
})

var express = require('express')

app = module.exports = express();
var secureServer = require('http').createServer(app);
secureServer.listen(3001);

var aws = require('aws-sdk')
var multer = require('multer')
var multerS3 = require('multer-s3')

    aws.config.update({
    secretAccessKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    accessKeyId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    region: 'us-east-1'
    });
    s3 = new aws.S3();

   var upload = multer({
   storage: multerS3({
    s3: s3,
    dirname: "uploads",
    bucket: "Your bucket name",
    key: function (req, file, cb) {
        console.log(file);
        cb(null, "uploads/profile_images/u_" + Date.now() + ".jpg"); //use  
     Date.now() for unique file keys
    }
  })
   });

 app.post('/upload', upload.single('photos'), function(req, res, next) {

 console.log('Successfully uploaded ', req.file)

 res.send('Successfully uploaded ' + req.file.length + ' files!')

})

ReferenceURL : https://stackoverflow.com/questions/28018855/upload-a-file-to-amazon-s3-with-nodejs

반응형