node.js - listobjects - Suba un archivo a Amazon S3 con NodeJS
s3 putobject params (5)
Encontré lo siguiente para ser una solución de trabajo ::
npm install aws-sdk
Una vez que haya instalado el aws-sdk, use el siguiente código reemplazando los valores con su donde sea necesario.
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");
}
});
});
Encontré el tutorial completo sobre el tema aquí en caso de que esté buscando referencias ::
Me encontré con un problema al intentar cargar un archivo en mi bucket de S3. Todo funciona, excepto que mis parámetros de archivo no parecen apropiados. Estoy usando Amazon S3 sdk para cargar desde nodejs a s3.
Estas son mis configuraciones de rutas:
var multiparty = require(''connect-multiparty''),
multipartyMiddleware = multiparty();
app.route(''/api/items/upload'').post(multipartyMiddleware, items.upload);
Esta es la función 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'');
}
});
});
};
Establecer
Body
param en una cadena como
"hello"
funciona bien.
Según el
doc
, el parámetro del
Body
debe tomar
(Buffer, Typed Array, Blob, String, ReadableStream) Datos del objeto.
Sin embargo, la carga de un objeto de archivo falla con el siguiente mensaje de error:
[Error: Unsupported body payload object]
Este es el objeto de archivo:
{ 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'' }
¡Cualquier ayuda será apreciada!
Entonces parece que hay algunas cosas que van mal aquí.
Según su publicación, parece que está intentando admitir cargas de archivos utilizando el middleware
connect-multiparty
.
Lo que hace este middleware es tomar el archivo cargado, escribirlo en el sistema de archivos local y luego establecer
req.files
en los archivos cargados.
La configuración de su ruta se ve bien, el problema parece estar con su función
items.upload()
.
En particular con esta parte:
var params = {
Key: file.name,
Body: file
};
Como mencioné al principio de mi respuesta,
connect-multiparty
escribe el archivo en el sistema de archivos local, por lo que deberá abrir el archivo y leerlo, luego cargarlo y luego eliminarlo en el sistema de archivos local.
Dicho esto, puede actualizar su método a algo como lo siguiente:
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();
}
});
});
});
};
Lo que esto hace es leer el archivo cargado del sistema de archivos local, luego subirlo a S3, luego eliminar el archivo temporal y enviar una respuesta.
Hay algunos problemas con este enfoque. En primer lugar, no es tan eficiente como podría ser, ya que para archivos de gran tamaño cargará todo el archivo antes de escribirlo. En segundo lugar, este proceso no admite cargas de varias partes para archivos grandes (creo que el límite es de 5 Mb antes de que tenga que hacer una carga de varias partes).
Lo que sugeriría en su lugar es que use un módulo en el que he estado trabajando llamado S3FS que proporciona una interfaz similar a la FS nativa en Node.JS pero abstrae algunos de los detalles, como la carga de varias partes y la API S3 (así como también agrega algunas funcionalidades adicionales como métodos recursivos).
Si S3FS que extraer la biblioteca S3FS , su código se vería así:
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();
});
};
Lo que esto hará es crear una instancia del módulo para el depósito proporcionado y las credenciales de AWS y luego crear el depósito si no existe. Luego, cuando llega una solicitud para cargar un archivo, abriremos una secuencia en el archivo y la usaremos para escribir el archivo en S3 en la ruta especificada. Esto manejará la pieza de carga de varias partes detrás de escena (si es necesario) y tiene el beneficio de realizarse a través de una transmisión, por lo que no tiene que esperar para leer todo el archivo antes de comenzar a cargarlo.
Si lo prefiere, puede cambiar el código a devoluciones de llamada de Promises . O use el método pipe() con el detector de eventos para determinar el final / errores.
Si está buscando algunos métodos adicionales, consulte la documentación para s3fs y siéntase libre de abrir un problema si está buscando algunos métodos adicionales o tiene problemas.
O usando promesas:
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);
}
Subir un archivo a AWS s3 y enviar la url en respuesta para acceder al archivo.
Multer es un middleware de node.js para manejar datos multiparte / formulario, que se utiliza principalmente para cargar archivos. Está escrito en la parte superior de busboy para una máxima eficiencia. mira este módulo npm here .
Cuando envíe la solicitud, asegúrese de que los encabezados tengan Content-Type es multipart / form-data. Estamos enviando la ubicación del archivo en la respuesta, que proporcionará la url, pero si desea acceder a esa url, haga público el depósito o de lo contrario no podrá acceder a él.
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!'')
})