I'm setting up the S3 upload function with koa(& serverless)
.
I made the S3 upload function and it looks working. But It had broken(? or empty) in the s3 bucket.
like this. broken image
My node project is using koa with serverless(bucket setting has done in here).
This is my package.json
{
// ...
"dependencies": {
"aws-sdk": "^2.464.0",
"dotenv": "^8.0.0",
"joi": "^14.3.1",
"koa": "^2.7.0",
"koa-body": "^4.1.0",
"koa-router": "^7.4.0",
"promise-mysql": "^3.3.2",
"serverless-http": "^2.0.2",
"serverless-offline": "^4.10.6"
},
// ...
}
And this is my app.js
const Koa = require('koa');
const koaBody = require('koa-body');
const routes = require('./api/index');
const app = new Koa();
app.use(koaBody({ multipart: true }));
app.use(routes.routes()).use(routes.allowedMethods());
app.use(ctx => {
ctx.body = 'hello world';
});
module.exports = app;
This is my router
const Router = require('koa-router');
const auth = new Router();
const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const fs = require('fs');
const BUCKET = 'chacha-s3-test';
auth.post('/image-up', async(ctx)=> {
const image = ctx.request.files.image;
const {
name, path, type
} = image
console.log('name :', name); //world.png
console.log('path :', path); //C:\<my local path>\upload_d7ac6297fa2d0fb09495695f1536a41a
console.log('type :', type); //image/png
const { key, url } = await putS3Object(
name,
path,
type,
).then(()=> getSignedUrl(name));
ctx.body = {key, url} // {}, no return..
})
function putS3Object(key, path, type) {
const stream = fs.createReadStream(path);
return S3.putObject({
Body: stream,
Bucket: BUCKET,
ContentType: type,
Key: key
}).promise();
}
function getSignedUrl(key) {
const params = {Bucket:BUCKET, Key: key};
return S3.getSignedUrl('getObject', params);
}
module.exports = auth;
This code can upload the file. But the image in s3 is broken. And it doesn't return the url.
The Image File is from a React FormData
e.target.files[0]
Do I need to write the react code?
I expected the uploaded image file in s3 bucket show me the original(world map picture). but it's just small square and black background(It has the almost same size(257.9KB) though).broken image
No error messages. And the image file had uploaded successfully. but the image in s3 bucket is broken.
How to fix it? Please help.
Thanks. Have a nice day!
You should use the upload()
method instead of putObject()
, simply because, upload()
method will accept a stream without a content-length defined whereas putObject()
does not. Here is how I use it currently:
const S3Client = new AWS.S3({apiVersion: '2006-03-01'});
const fs = require('fs');
const upload = (bucket, key, readable) => {
const params = {Bucket: bucket, Key: key, Body: readable};
return S3Client.upload(params).promise();
};
(async () => {
try {
const readable = fs.createReadStream(some path here...);
const uploaded = upload(config.destination.bucket, config.destination.key, readable);
// Further stuff goes here....
} catch(e) {
console.log('Error happend while uploading: ', e.message)
}
})();
More about the upload()
method, you can read here.
I hope this will help.