vue express uploading multiple files to amazon s3 - node.js

i need a help on how to upload multiple files image on amazon S3. i let's say that i have three input like this
<template lang="html">
<form enctype="multipart/form-data" #submit.prevent="sendFile">
<input type="file" ref="file1" #change="selectFile1">
<input type="file" ref="file2" #change="selectFile2">
<input type="file" ref="file3" #change="selectFile3">
<div class="field">
<button class="button is-info">Send</button>
</div>
</form>
</template>
and my frontend vue script looks like this
<script>
import _ from 'lodash'
export default {
name: 'BulkUpload',
data() {
return {
file: "",
message: "",
error: false,
sendFiles: []
}
},
methods: {
selectFile1() {
this.file = this.$refs.file1.files[0]
this.sendFiles.push(this.file)
console.log(this.sendFiles);
},
selectFile2() {
this.file = this.$refs.file2.files[0]
this.sendFiles.push(this.file)
console.log(this.sendFiles);
},
selectFile3() {
this.file = this.$refs.file3.files[0]
this.sendFiles.push(this.file)
console.log(this.sendFiles);
},
sendFile() {
let formData = new FormData()
_.forEach(this.uploadFiles, file => {
formData.append('file', file)
})
var self = this
axios.post('http://localhost:3000/image/bulkupload', formData)
.then(function(response) {
console.log(response);
self.message = "File has been uploaded"
self.file = ""
self.error = false
})
.catch(function(err) {
self.message = "Something went wrong"
self.error = true
console.log(err);
})
}
}
}
</script>
after sending it in using formData to the express server, my image route will handle it with this code
const sendingImage = require('../helper/sendingImage');
router.post('/bulkupload', sendingImage.upload.array("file"), (req, res) => {
var promises=[];
for(var i = 0; i < req.files.length; i++) {
var file = req.files[i];
promises.push(sendingImage.uploadLoadToS3(file));
}
Promise.all(promises).then(function(data){
res.send('Uploadedd');
console.log('success');
}).catch(function(err) {
console.log('failed');
res.send(err.stack);
})
})
and my helper looks like this
const multer = require('multer');
const aws = require('aws-sdk');
aws.config.update({
accessKeyId: <my access id>,
secretAccessKey: <my secret key>
})
const upload = multer({
dest: './uploads/'
})
function uploadLoadToS3(ObjFile){
var params = {
ACL :'public-read',
Body : new Buffer(ObjFile.buffer),
Bucket:'vue-express-upload',
ContentType:ObjFile.mimetype,
Key:ObjFile.originalname
}
return s3.upload(params).promise();
}
module.exports = {
upload,
uploadLoadToS3
}
to be honest, my code works without any problem. it send response status 200 without any error.
but the problem is, when i check my S3 bucket, it doesn't have any uploaded file in it. it's still empty.
is there anything wrong with my code ?

The solution I found for using aws-sdk. The good that I will also use this solution and my projects.
Credits: StackOver - Answer
Reference: Multer-s3
In your helper file you'll leave it like this:
const aws = require('aws-sdk')
const multer = require('multer')
const multerS3 = require('multer-s3')
aws.config = new aws.Config({
accessKeyId: <my access id>,
secretAccessKey: <my secret key>,
region: <my region>
})
const s3 = new aws.S3()
const upload = multer({
storage: multerS3({
s3: s3,
acl: 'public-read',
bucket: 'vue-express-upload',
contentType: function(req, file,cb){
cb(null, file.mimetype)
},
key: function (req, file, cb) {
cb(null, file.originalname)
}
})
})
module.exports = upload
The key of the file you can also change to something more unique, like the date / minutes / seconds. It is at your discretion, I used the filename as key.
In your router the route will look like this:
const upload = require('../helper/sendingImage')
router.post('/bulkupload', upload.array('files'), (req, res) => {
console.log('success')
//console.log(req.files)
res.send('Uploadedd')
//res.send(req.files)
})
To view upload data:
router.post('/bulkupload', upload.array('files'), (req, res) => {
res.send({
status: 200,
data: {
sucess: true,
file: req.files
}
})
})
If there is no middleware file, it simply will not send. Will not return error. The only errors that can return are those of AWS access information.
Note:I used the postman.

Related

how can i upload multiple images to s3 using vuejs

how can i upload multiple images to amazon s3
this is my middleware for image upload
const aws = require("aws-sdk");
const multer = require("multer");
const multerS3 = require("multer-s3");
aws.config.update({
secretAccessKey: process.env.AWSSecretKey,
accessKeyId: process.env.AWSAccessKeyId
});
const s3 = new aws.S3();
const upload = multer({
storage: multerS3({
s3: s3,
bucket: 'ajibade',
acl: 'public-read',
metadata: (req, file, cb) => {
cb(null, { fieldName: file.fieldname });
},
key: (req, file, cb) => {
cb(null, Date.now().toString())
}
})
})
module.exports = upload;
this is how i upload the file
<label class="choosefile-button">
<input
type="file"
#change="onFileSelected1"
>
<p style="margin-top: -70px">{{ fileName }}</p>
</label>
<label class="choosefile-button">
<input
type="file"
#change="onFileSelected2"
>
<p style="margin-top: -70px">{{ fileName }}</p>
</label>
how i call the function
methods: {
onFileSelected1(event) {
this.selectedFile = event.target.files[0]
console.log(this.selectedFile)
this.fileName = event.target.files[0].name
},
onFileSelected2(event) {
this.selectedFile = event.target.files[0]
console.log(this.selectedFile)
this.fileName = event.target.files[0].name
},
}
each time i click on either onFileSelected1 or onFileSeleted2 it uploads the same images for the both inputs
this is my post request
router.post(`/products`, upload.single("photo"), async (req, res) => {
console.log(res);
try {
let product = new Product();
product.photo = req.file.location;
await product.save();
} catch (error) {
console.log(error);
}
});
please how can i go about this
This blog post explains quite in depth how it's done.
Basically what you need to do is add a <input type="file" multiple /> and in your upload function turn it into multipart/form-data. Then when you upload it to your backend, you use multer and multer-s3 to send it to S3.
I think you've mixed up a few concepts here, your upload function looks like a route that is supposed to be in the backend of the application, where you then send the request to upload files using for example axios or the fetch API.

How to access image from uploaded on nestjs server

I have a nestjs server and I have uploaded the images but when I try to access to those images they are a bunch of stuff that cant be interpreted as an image.(I also tried converting them to blob which then I converted to objectURL and then set it as src for img tag but that didnt work either).Upload code:
#Post('upload')
#UseInterceptors(FileInterceptor('file',{
storage: diskStorage({
destination: './uploads',
filename: editFileName,
}),
fileFilter: imageFileFilter,
}))
uploadFile(#UploadedFile() file){
console.log(file);
file.filename = file.originalname;
const response = {
originalname: file.originalname,
filename: file.filename,
}
return response;
}
The above upload code perfectly saves the image as index-53a2.jpg in my uploads folder. Now trying to get the image using get req by:
#Get()
display(#Res() res){
res.sendFile('index-53a2.jpg',{ root: './uploads' })
}
logging response for this it gives some string of unreadable(probably encoded) stuff.
code I used for testing:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
$(function () {
$('#abc').on('submit', function (e) {
e.preventDefault();
$.ajax({
url: 'http:/localhost:3000/student/upload',
method:'POST',
data: new FormData(this),
contentType: false,
cache:false,
processData:false,
success: function (data) {
console.log(data);
// location.reload();
}
});
});
});
function fun(){
$.ajax({
url: 'http://localhost:3000/student',
success: function(data){
console.log('s',data);
let blob = new Blob([data]);
var objectURL = URL.createObjectURL(blob);
document.getElementById('img').src = objectURL;
},
error: function(data){
console.log('e',data);
}
})
}
</script>
</head>
<body>
<img alt="Image" id="img">
<form enctype= "multipart/form-data" id="abc">
<input type="file" name="file" required accept="image/*"><br>
<input name="submit" type="submit" value="Submit">
</form>
<button onclick="fun()">Button</button>
</body>
</html>
Also this html code is just for testing, my main purpose is to use this server so that I can take student image and data(contains basic details like name, phone, etc.) from angular and save it on mongoDB. Also I dont have any idea how to send my image from angular to nestjs and how to save it(and where to save it on MongoDB or Nestjs server and how)
Any help would be greatly appreciated!!!
Thanks in advance.
To access to your files with NestJs you need to define your static assets directory name in the main.ts using the .useStaticAssets method on your app
app.useStaticAssets(join(__dirname, '..', 'public'), {
index: false,
prefix: '/public',
});
I found solution to this. So what we have to do is basically append all our data in formData and send it in the request from angular.
let formData = new FormData();
formData.append('image',this.image);
Now this image attribute is taken from the function triggered by the onchange on the input tag that takes image as input.
onChange(event){
this.image = event.target.files[0];
}
Now we send it to backend from our service.
sendReq(formData){
this.http.post('localhost:3000/your_route',formData);
}
Now while accessing it from the Nestjs server we use FileInterceptor.
import { Controller, Get, Post, Res, UploadedFile, UseInterceptors, Body } from '#nestjs/common';
import { FileInterceptor } from '#nestjs/platform-express';
import { editFileName, imageFileFilter } from './funcs';
import { diskStorage } from 'multer';
#Post('your_route')
#UseInterceptors(FileInterceptor('image',{
storage: diskStorage({
destination: './uploads',
filename: editFileName,
}),
fileFilter: imageFileFilter,
}))
async func(#UploadedFile() file, #Body() body){
try{
body.image = file.filename;
body.view = false;
let res = await this.yourService.yourFunc(body);
return {
'success': true,
'data': res
}
}
catch(err){
console.log(err);
return {
'success': false,
'data': err
}
}
}
const imageFileFilter = (req, file, callback) => {
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
return callback(new Error('Only image files are allowed!'), false);
}
callback(null, true);
};
const editFileName = (req, file, callback) => {
const name = file.originalname.split('.')[0];
const fileExtName = '.'+file.originalname.split('.')[1];
const randomName = Array(4)
.fill(null)
.map(() => Math.round(Math.random() * 16).toString(16))
.join('');
callback(null, `${name}-${randomName}${fileExtName}`);
};
So this way we get a uploads folder in our root directory and image uploaded to our server gets saved here. To save the image the name I have user here is the name of the file being uploaded + '-' + a sequence of random char and int of length 4(Here you can have logic of your own).

Fetch /POST request to Server: Empty array when receiving multipart/form-data;

Im trying to upload an image (ReactJs) to my server (NodeJs+ Express+ multerJs) to digital Ocean.
Im using a POST Request with multipart/form-data;
I get a succesfull message from multerJs but I can see in the log on the server that the files: [] has an empty array. And that Digital Ocean didnt add any file of course.
When i do the same Post request with the form without handling the submission of the form ,everything is working and the Files array is not empty.the code above is working :
<form method="post" enctype="multipart/form-data" action="http://localhost:3004/upload_image_test_4" > </form>
Client-Side React.js :
export default class Select_size extends React.Component {
on_form_submit = (e) => {
e.preventDefault();
const fileInput = this.state.file;
const formData = new FormData();
formData.append('file', fileInput);
const options = {
method: 'POST',
body: formData,
headers: {
'Access-Control-Allow-Origin': '*',
Accept: 'application/json',
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
}
};
var url =
this.state.action_link +
'?url=' +
this.state.id_user +
'/' +
this.state.id_draft +
'&name=' +
this.state.name_file;
fetch(url, options);
};
onChange = (e) => {
this.setState({ file: e.target.files[0] });
};
constructor(props) {
super(props);
this.state = {
files: [],
};
this.onChange = this.onChange.bind(this);
}
render() {
return (
<form onSubmit={this.on_form_submit} enctype="multipart/form-data">
<input type="file" name="myImage" onChange={this.onChange} />
<button type="submit">Upload</button>
</form>
)}
}
Server-side (Node.js/ ExpressJs/Multer/Digital Ocean) :
const express = require('express');
const router = express.Router();
const bodyParser = require('body-parser');
const aws = require('aws-sdk');
const spacesEndpoint = new aws.Endpoint('fra1.digitaloceanspaces.com');
const s3 = new aws.S3({
endpoint: spacesEndpoint,
accessKeyId: 'myID',
secretAccessKey: 'MySecretKey'
});
const upload = multer({
storage: multerS3({
s3: s3,
bucket: 'bucketName',
acl: 'public-read',
key: function(request, file, cb) {
cb(null, urlBucket + name_image);
}
})
}).array('upload', 1);
router.post('/upload_image_test_4', function(request, response, next) {
upload(request, response, function(error) {
console.log(request, 'the request');
if (error) {
console.log(error);
return response.json(error, 'error');
}
console.log('File uploaded successfully.');
return response.json('success its uploaded to digital ocean');
});
});
module.exports = router;
If anyone can help me with that ! (I already 'googled' insanely,,,)
Thanks !!
//EDIT I found a solution to my own question... on the github page dedicated to a bug related to Next.js :
The file was not send to the request for some reasons.
I used axios in this way and its now working :
React-js :
sendFile = (e) => {
const data = new FormData();
const file = e.target.files[0];
data.append('avatar', file);
axios
.post('http://localhost:3004/upload_test_stack_2', data)
.then(console.log)
.catch(console.error);
}
The server side (nodeJs) :
const upload = multer({
storage: multerS3({
s3: s3,
bucket: 'My Bucket',
acl: 'public-read',
key: function(request, file, cb) {
cb(null, file.originalname);
}
})
});
router.post('/upload_test_stack_2', upload.single('avatar'), (req, res)
=> {
console.log(req.file, 'The file appears here');
return res.sendStatus(200);
});
Files from input are not an array but FileArray, try [...e.target.files][0]
Related to Event Pooling in React and async behavior of setState.
Modify onChange handler:
Method 1:
Put the file to variable and set it in setState.
onChange = (e) => {
const uploadFile = e.target.files[0] ;
this.setState({ file: uploadFile });
};
Method 2 with event.persist():
onChange = (e) => {
e.persist();
this.setState({ file: e.target.files[0] });
};

Multipart File upload in MERN Stack

I am trying to Implement File upload feature using multipart to speed up upload for big file size.
I am unable to figure out why this is not working.
I am providing environment variables via console for now.
When I click send button, nothing happens. Both my servers are running fine (I am quite sure of them)
Issue:
1> when I do
axios.post(`http://localhost:4000`, data)
it throws an error. How shall I post my file (data) to backend?
Please point out the mistakes or things to be done.
Thanks in Advance!
Following is my FileUpload.js
import React, { Component } from 'react';
import axios from 'axios';
class FileUpload extends Component {
constructor (props) {
super(props);
this.submitFile = this.submitFile.bind(this);
this.fileInput = React.createRef();
}
submitFile = (event) => {
event.preventDefault();
var data = {
file: this.fileInput.current.files[0],
name: this.fileInput.current.files[0].name
};
axios.post(`http://localhost:4000`, data)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<form onSubmit={this.submitFile}>
<input type='file' ref={this.fileInput} />
<button type='submit'>Send</button>
</form>
);
}
}
export default FileUpload;
My backend Node upload.js looks like following:
const multer = require('multer');
const multerS3 = require('multer-s3');
const AWS = require('aws-sdk');
var cred = require('../aws/config')
const AWS_SECRET_ACCESS = cred.access();
const AWS_ACCESS_KEY = cred.awskey();
// configure the keys for accessing AWS
AWS.config.update({
accessKeyId: process.env.AWS_SECRET_ACCESS,
secretAccessKey: process.env.AWS_ACCESS_KEY,
region: ''
});
// create S3 instance
const s3 = new AWS.S3();
const upload = multer({
storage: multerS3({
s3:s3,
bucket: '',
metadata: function (req, file, cb) {
cb(null, {fileName: 'uploadit'});
},
key: function (req, file, cb) {
cb(null, Date.now().toString())
}
})
})
module.exports = upload;
I always upload my photos on cloudinary.
You can save them locally too but on the long term I don't think this is a solution.
Backend
import express from 'express';
import webpackMiddleware from 'webpack-dev-middleware';
import webpack from 'webpack';
import webpackConfig from './webpack.config.js';
const app = express();
app.use(webpackMiddleware(webpack(webpackConfig)));
const port = process.env.PORT || 5000;
const cloudinary = require('cloudinary');
cloudinary.config({
cloud_name: 'your cloud name',
api_key: 'your api key',
api_secret: 'your api secret'
});
app.use(multipartMiddleware);
app.post('/images', multipartMiddleware, (req, res) => {
// file upload
let formData = Object.values(req.files);
let photoName = Object.keys(req.files);
cloudinary.uploader.upload(
formData[0].path,
function () { res.json('Uploaded!')},
{
public_id: photoName[0],
crop: 'scale',
width: 1200,
height: 400,
quality: 100,
tags: ['usedCars', 'usedCars']
}
)
});
app.listen(port, () => {
console.log('Your app on port:', port);
});
Frontend
// input type file
<input type="file"
accept="image/*"
onChange={evt => this.updateFileValue(evt)}
id="carPhoto"/>
// updating state
updateFileValue(evt) {
this.setState({
carPhoto: evt.target.files[0]
});
}
// post request
Apis.addCarsList(this.state).then((res) => {
const fd = new FormData();
const photoName = "a name for your photo, I usually get the mongoId as a photo name";
fd.append(res.data, this.state.carPhoto, photoName);
axios.post('/images', fd).then((res) => {
// do w/e
});
})
Apparently you're doing almost everything correct, except for one small detail that caught my attention.
your fileName is defined from files.name, which is undefined (try to console.log that to verify). What you need to do is give it a unique name, like for example a timestamp.
app.post('/upload', (request, response) => {
const form = new multiparty.Form();
form.parse(request, async (error, fields, files) => {
if (error) throw new Error(error);
try {
const path = files.file[0].path;
const buffer = fs.readFileSync(path);
const type = fileType(buffer);
const fileName = Date.now().toString();
const data = await uploadFile(buffer, fileName, type);
return response.status(200).send(data);
}
catch (error) {
return response.status(400).send(error);
}
});
});
Also make sure you're proxying your requests: https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development
Some additional debugging tricks, if you haven't tried that yet:
Try to create a simple get route in your server just to make sure that client and server are talking to each other.
Try to create first a get request to list your buckets to make sure that the communication with S3 works as expected: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#listBuckets-property
I hope this helps!
Cheers!

axios upload to node.js API results in files in aws s3 becoming unreadable

Screen of UploadScreen of DownloadWhenever I utilize the client side upload panel the files that get uploaded to the bucket are named correctly but wont open. They are also a slightly different size from the front end uploaded version. I'm wondering if something in how i'm handling buffers / reading the files is off but I just started working with them yesterday so i'm fairly lost. If any of you based genius programmers could provide some insight into this issue I'd be eternally grateful!!
The overall goal is the ability to upload files to an aws s3 bucket of any file type, then be able to download these files without them being modified or rendered unopenable.
server side javascript;
var express = require("express");
var mongodb = require("mongodb");
var _ = require("lodash");
var bodyParser = require("body-parser");
var app = express();
var router = express.Router();
var mongoose = require("mongoose");
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-1'});
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
...
...
...
router.post('/upload', function (req, res) {
var file = new File({name: req.body.fileName, type: req.body.contentType, buffer: req.body.file});
var fs = require('fs');
var fileStream = fs.createWriteStream(req.body.fileName);
fileStream.write(req.body.file)
fileStream.end(function () { console.log('done'); });
fileStream.on('error', function(err) {
console.log('File Error', err);
});
fs.readFile(req.body.fileName, (err, data) => {
if (err) throw err;
console.log(data);
const params = {
Bucket: req.body.crystalName,
Key: req.body.fileName,
Body: data
};
s3.upload(params, function(s3Err, data) {
if (s3Err) {
console.log(s3Err);
} else {
res.send(`File uploaded successfully at ${data.Location}`);
console.log(`File uploaded successfully at ${data.Location}`);
}
});
});
});
client side upload function (vue.js);
<template>
<div class="main">
<input v-model="crystalName" placeholder="Crystal Name" />
<input type="file" #change="onFileChange"/>
<button v-on:click="uploadToCrystal">Upload</button>
<span>{{this.file}}</span>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'crystalviewer',
props: ['user'],
data: function () {
return {
crystalName: '',
fileName: '',
contentType: '',
file: ''
}
},
methods: {
onFileChange (file) {
let vue = this
var reader = new FileReader()
this.fileName = file.target.files[0].name || file.dataTransfer.files[0].name
this.contentType = file.target.files[0].type || file.dataTransfer.files[0].type
console.log(this.contentType)
var start = 0
var stop = file.target.files[0].size
var blob = file.target.files[0].slice(start, stop)
reader.onloadend = function (file) {
vue.file = file.target.result
}
reader.readAsText(blob, 'utf-8')
},
uploadToCrystal () {
let vue = this
axios.post('https://api.mystic-crm.com/crystalviewer/upload', {
crystalName: vue.crystalName,
fileName: vue.fileName,
contentType: vue.contentType,
file: vue.file
})
.then(response => {
console.log(response)
})
.catch(err => {
console.log(err)
})
}
}
}
</script>
<style scoped lang="less">
.main {
}
</style>
To get files after an upload run a get against;
https://api.mystic-crm.com/crystalviewer/contents/:crystalName/:fileName
where;
:crystalName = testcrystalmystic
:fileName = your_file_to_get
Turns out switching to Multiparty was the solution, now I can upload via forms. Apparently axios doesn't support file uploads but forms do so that was a fun revelation. edit added working front end
var express = require("express");
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-1'});
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
var multiparty = require('multiparty');
router.post('/upload', function (req, res) {
var form = new multiparty.Form();
var destPath;
var crystalName;
form.on('field', function(name, value) {
if (name === 'crystalName') {
crystalName = value
} else if (name === 'fileName') {
destPath = value;
}
});
form.on('part', function(part) {
s3.putObject({
Bucket: crystalName,
Key: destPath,
ACL: 'public-read',
Body: part,
ContentLength: part.byteCount
}, function(err, data) {
if (err) throw err;
console.log("done", data);
res.end("OK");
console.log("https://s3.amazonaws.com/" + crystalName + '/' + destPath);
});
});
form.parse(req);
});
front end ex;
<template>
<div class="main">
<form v-on:submit="submit">
<input name="crystalName" placeholder="Crystal Name" />
<input name="fileName" v-model="fileName" placeholder="File Name" v-show="false" />
<input name="file" type="file" #change="onFileChange"/>
<input type="submit" value="Upload File" />
</form>
</div>
</template>
<script>
export default {
name: 'crystalviewer',
props: ['user'],
data: function () {
return {
fileName: '',
modal: ''
}
},
methods: {
submit (event) {
let vue = this
var form = document.forms[0]
var request = new XMLHttpRequest()
request.open('POST', 'https://api.mystic-crm.com/crystalviewer/upload', true)
request.setRequestHeader('accept', 'multipart/form-data')
event.preventDefault()
var formData = new FormData(form)
request.send(formData)
request.onreadystatechange = function () {
if (request.readyState < 4) {
vue.modal = 'loading'
} else if (request.readyState === 4) {
if (request.status === 200 || request.status < 300) {
vue.modal = 'success'
console.log('success')
} else {
vue.modal = 'failure'
console.log('failure')
}
}
}
},
onFileChange (file) {
this.fileName = file.target.files[0].name || file.dataTransfer.files[0].name
}
}
}
</script>
<style scoped lang="less">
.main {
}
</style>
React Hooks Version for anyone searching for this
Front End:
import React, {useState} from 'react'
import axios from 'axios'
function Amazonuploadtest() {
const [file, setFile] = useState('')
const submitFile = (e) => {
e.preventDefault();
console.log(file[0])
const formData = new FormData();
formData.append('file', file);
axios.post(`http://localhost:4000/upload`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
console.log(response)
}).catch(error => {
console.log(error)
});
}
return (
<div>
<form onSubmit={submitFile} enctype="multipart/form-data" style={{paddingTop: 200}}>
<input label='upload file' type='file' name="upl" onChange={e => setFile(e.target.files[0])} />
<button type='submit'>Send</button>
</form>
</div>
);
}
export default Amazonuploadtest
Back End:
require('dotenv').config({ path: __dirname + '/.env' })
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const path = require('path')
const AWS = require('aws-sdk');
const fs = require('fs');
const multer = require('multer');
const multerS3 = require('multer-s3');
app.use(cors());
app.use(bodyParser.json());
app.use(cookieParser());
// ####################################### ALL AWS STUFF GOES HERE ###############################################################################################
AWS.config.update({
secretAccessKey: 'YOUR KEY GOES HERE',
accessKeyId: 'YOUR KEY GOES HERE',
region: 'YOUR REGION GOES HERE -> You can find it in your bucket URL',
});
const s3 = new AWS.S3();
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'YOUR BUCKET NAME -> Find it in your Bucket URL',
key: function (req, file, cb) {
cb(null, Date.now().toString() + `.png`); // gives every image upload a unique URL
}
})
});
app.post('/upload', upload.array('file',1), function (req, res, next) {
const key = req.files[0].key
console.log(key)
res.send("Uploaded!");
// We return the key here so that we can then save it as a URL in MongoDB -> allows
// you to call the image URL when rending the image on the front end.
// example -> let avatarURL = `https://s3.amazonaws.com/YOURBUCKETNAME/${key}`
});

Resources