I tuoi problemi nel caricare un file su un bucket di Amazon, con il servizio AWS S3, usando un server Node e un fron-end React sono finalmente terminati: oggi ti presento la soluzione!
Quick Brief
Il nostro faraway goal è creare una piattaforma per l’acquisto e la gestione di corsi online.
Abbiamo identificato gli elementi chiave per la realizzazione del progettto, e creato un sistema per il login delgi utenti. Siamo quindi passati alla gestione delle transazioni con Stripe, e messo in secondo piano l’upload dei file.
Ora riprendiamo in mano il progetto e vediamo come gestire l’Upload file AWS S3, così da poterli facilmente visualizzare con un public url.
Project Goal
Al termine di questo progetto avremo:
- front-end React con un semplice form per l’upload di uno o più file
- back-end Node e MondoDB per l’upload handling e la visualizzazione dei file caricati
- RESTful api per l’upload generico dei file e per la creazione di un prodotto da vendere
Prerequisiti
- account AWS atttivo e funzionante
- back-end node configurato (express, body-parser, cors, helmet, dotenv)
- React app con router abilitato
Crezione Bucket S3
Il primo passo è accedere alla console AWS, navigare sul servizio S3 e creare un bucket: il nostro contenitore per i file.

Nel funnel di creazione dovremo prestare attenzione ad alcune cose:
- possiamo scegliere un quasliasi nome, purché non sia già in uso presso qualche altro utente AWS.
- dobbiamo depennare “Block all public access” allo STEP 3, in caso sarà impossibile ottenere un public URL funzionante.
Creato il bucket, prima di procedere oltre è necessario accedere alle KEY di Amazon.
In altro a destra, con un hover sul nostro nome utente si apre un dropdown contenente la voce “My Security Credential”, l’unica di nostro interesse. Clicchiamoci.
You are accessing the security credentials page for your AWS account. The account credentials provide unlimited access to your AWS resources.
Il disclaimer di AWS è sufficientemente diretto. Attento all’uso che ne fai delle credenziali che andrai a creare: condividile attentamente.
Apriamo il collapse Acces keys (acces key ID and secret access key), quindi seguiamo la procedura guidata per la creazione delle chiavi.
Andiamo quindi ad integrarle nel nostro file .env, RISPETTANDO IL NOME FORNITO:
AWS_ACCESS_KEY_ID=**** AWS_SECRET_ACCESS_KEY=**** AWS_REGION=**** S3_BUCKET=api-monolith
Node Back-End | Handling S3 Upload File RESTfully
Abbiamo bisogno di alcuni pacchetti:
npm i aws-sdk, multer, multer-s3
Definiamo una rotta per l’upload dei file. In questo momento lavoro alle API V1, quindi quella completa sarà:
localhost:8001/V1/uploadfile
const express = require('express') const router = express.Router() // import controller const ctrl = require('./utils.controller') //define utils routes router.route("/uploadfile") .post(ctrl.uploadFile) //post route module.exports = router
All’interno del file utils.controller.js andiamo a gestire le funzioni, che saranno in grado fare l’upload su S3 con Node di file multipli.
Inziamo ad importare i pacchetti che gestiranno l’upload:
// handling mutlipart form-data const multer = require('multer') // avoid caching data const multerS3 = require('multer-s3') // aws istance (automatic config from .env file) const AWS = require("aws-sdk") // set s3 istances (again, automatic config from .env file) // consider the fact that we will overwrite this configuration const s3 = new AWS.S3()
Quindi procediamo a definire ed esportare il nostro middleware:
// at this point upload and handleUpload have to be defined const uploadMiddleware = [upload.array("file"), handleUpload] module.exports = { uploadMiddleware }
Ora creiamo una nuova istanza di multer:
const upload = multer({ storage: multerS3({ s3: s3, bucket: 'api-monolith', // need to specify bucket acl: 'public-read', // set to public-read otherwise get XML file contentType: multerS3.AUTO_CONTENT_TYPE, // get content-type key: function (req, file, cb) { /* * Define the fileName * Can be custom, the same, or hybrid: */ const fileName = (Date.now() + "-" + file.originalname) cb(null, fileName) } }) })
Ora la inviamo una risposta al client contenete i ref ai file appena caricati:
const handleUpload = (req, res) => { // get files location: const locations = req.files.map((item) => item.location) res.send({ message: 'Successfully uploaded files!', files: locations }) }
Et voilà backend configurato.
Si è acerbo, ma funziona!
Basterebbe implementare qualche controllo aggiuntivo e un corretto sistema di gestione degli errori. Prossimamente!
React: aws s3 form upload
Gestendo l’intero processo da back-end, il front-end si limita a passare i file binari.
Installiamo la librerie axios, per gestire agevolmente l’upload dei file :
npm i axios
Quiindi definiamo un input mutliple:
<div> <h1>Upload File Form</h1> <input multiple type="file" name="file" onChange={this.onChangeHandler} /> <button type="button" className="btn btn-success" onClick={this.onClickHandler}>Upload</button> </div>
E ora le funzioni:
constructor(props) { super(props) this.state = { selectedFile: null } } onChangeHandler = (event) => { this.setState({ ...this.state, selectedFile: event.target.files, }) } onClickHandler = (event) => { const data = new FormData() for (var x = 0; x < this.state.selectedFile.length; x++) { data.append('file', this.state.selectedFile[x]) } // POST url axios.post("http://localhost:8001/v1/uploadfile", data, { // receive two parameter endpoint url ,form data }) .then(res => { // then print response status console.log(res.statusText) }) .catch(err => { console.log(err) }) }
Tanto margine di implementazione, ma per il momento possiamo considerarci soddisfatti!
In un futuro update, aggiungeremo il supporto a mongo DB!
Un caldo abbraccio, Andrea!