OpenClassrooms devient une université américaine accréditée.
Découvrez ce que cela change pour vousTable des matières
- Partie 1
Build a Simple Express Server
- Partie 2
Build a RESTful API
- Partie 3
Make Your API Secure
- Partie 4
Add Image Upload to Your API
Modify Routes to Take Files Into Account
For your middleware to work on your routes, you will need to modify them slightly, as a request containing a file from the front end will have a different format.
#Modify the POST Route
First, add your multer middleware to your POST route in your stuff router:
const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const multer = require('../middleware/multer-config');
const stuffCtrl = require('../controllers/stuff');
router.get('/', auth, stuffCtrl.getAllStuff);
router.post('/', auth, multer, stuffCtrl.createThing);
router.get('/:id', auth, stuffCtrl.getOneThing);
router.put('/:id', auth, stuffCtrl.modifyThing);
router.delete('/:id', auth, stuffCtrl.deleteThing);
module.exports = router;
You now need to update your controller to correctly handle the new incoming request:
exports.createThing = (req, res, next) => {
req.body.thing = JSON.parse(req.body.thing);
const url = req.protocol + '://' + req.get('host');
const thing = new Thing({
title: req.body.thing.title,
description: req.body.thing.description,
imageUrl: url + '/images/' + req.file.filename,
price: req.body.thing.price,
userId: req.body.thing.userId
});
thing.save().then(
() => {
res.status(201).json({
message: 'Post saved successfully!'
});
}
).catch(
(error) => {
res.status(400).json({
error: error
});
}
);
};
So what are we doing here?
To add a file to the request, the front end needed to send the request data as form-data as opposed to JSON. The request body contains a
thingstring, which is simply a stringifiedthingobject. Therefore, you need to parse it usingJSON.parse()to get a usable object.You need to resolve the full URL because your image
req.file.filenameonly contains the filename segment. Usereq.protocolto get the first segment ('http', in this case). Add the'://', and then usereq.get('host')to resolve the server host ('localhost:3000'). Finally, add'/images/'and the filename to complete your URL.
If you save the controller as is and try out the app (remember to use the part 4 section!), you will see that almost everything works. You only get a 404 error when trying to fetch the image, even though it looks like your URL is correct. So what's happening here?
Well, you are making a GET request to http://localhost:3000/images/<image-name>.jpg . It seems simple, but remember that the Express app is running on localhost:3000 , and you haven't told it how to react to requests going to that endpoint, so it is returning a 404 error. Therefore, you need to tell your app.js how to handle those requests, serving up your static images folder.
You will need a new import in app.js :
const path = require('path');
Add the following route handler just above your current routes:
app.use('/images', express.static(path.join(__dirname, 'images')));
This tells Express to serve up the static resource images (a sub-directory of your base directory, __dirname ) whenever it receives a request to the /images endpoint. Save and refresh the app in the browser: things should now be working properly! Now on to the PUT route!
#Modify the PUT Route
Modifying the PUT route is slightly more complicated, as you have to take into account both possibilities: the user has updated the image, or they have not. In the first case, you will receive form-data and file; in the second case, you will just receive JSON data.
First, add multer as middleware to your PUT route:
const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const multer = require('../middleware/multer-config');
const stuffCtrl = require('../controllers/stuff');
router.get('/', auth, stuffCtrl.getAllStuff);
router.post('/', auth, multer, stuffCtrl.createThing);
router.get('/:id', auth, stuffCtrl.getOneThing);
router.put('/:id', auth, multer, stuffCtrl.modifyThing);
router.delete('/:id', auth, stuffCtrl.deleteThing);
module.exports = router;
Now modify your modifyThing() function to check if you have received a new file, and react accordingly:
exports.modifyThing = (req, res, next) => {
let thing = new Thing({ _id: req.params._id });
if (req.file) {
const url = req.protocol + '://' + req.get('host');
req.body.thing = JSON.parse(req.body.thing);
thing = {
_id: req.params.id,
title: req.body.thing.title,
description: req.body.thing.description,
imageUrl: url + '/images/' + req.file.filename,
price: req.body.thing.price,
userId: req.body.thing.userId
};
} else {
thing = {
_id: req.params.id,
title: req.body.title,
description: req.body.description,
imageUrl: req.body.imageUrl,
price: req.body.price,
userId: req.body.userId
};
}
Thing.updateOne({_id: req.params.id}, thing).then(
() => {
res.status(201).json({
message: 'Thing updated successfully!'
});
}
).catch(
(error) => {
res.status(400).json({
error: error
});
}
);
};
In this modified version of the function:
First create a new instance of your
Thingmodel with the received_idso as not to cause problems when trying to update thatThingin the database.If you receive a new file with the request (via
multer), handle the form-data and generate the image URL.If you do not receive a new file, capture the request body JSON.
Save the updated
Thingto the database.
Congratulations! Your app now correctly handles file uploads both when putting new things up for sale, and when modifying existing ones.
#Let's Recap!
JSON.parse()turns a stringified object into a usable JavaScript Object.To reconstruct the full URL of a saved file, you'll need
req.protocolandreq.get('host'), joining them with'://', followed byreq.file.filename.Tell your server to serve static files on a given route using
express.static()andpath.join().
In the next chapter, you'll see how to expand the back end's delete function!
- Formations jusqu’à 100 % financées
- Date de début flexible
- Projets professionnalisants
- Mentorat individuel