Skip to content

Commit 134d3a1

Browse files
authored
Video-37-Upload-Product-Image (basir#37)
1 parent cedb56f commit 134d3a1

File tree

7 files changed

+70
-9
lines changed

7 files changed

+70
-9
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,7 @@ Feel free to take a look at the course preview and enroll if it is along with yo
311311
1. handle form submit
312312
2. create updateProduct
313313
3. save product in backend
314-
37. Delete Product
315-
1. update ProductListScreen.js
316-
2. handle delete button
317-
3. rerender after deletion
318-
38. Upload Product Image
314+
37. Upload Product Image
319315
1. npm install multer
320316
2. create routes/uploadRoute.js
321317
3. import express and multer
@@ -332,13 +328,17 @@ Feel free to take a look at the course preview and enroll if it is along with yo
332328
14. call uploadProductImage()
333329
15. create uploadProductImage in api.js
334330
16. update server.js
335-
39. Build Project
331+
38. Build Project
336332
1. create build script for frontend
337333
2. create build script for backend
338334
3. update sever.js to serve frontend build folder and uploads folder
339335
4. stop running frontend
340336
5. npm run build
341337
6. check localhost:5000 for running website and showing images
338+
39. Delete Product
339+
1. update ProductListScreen.js
340+
2. handle delete button
341+
3. rerender after deletion
342342
40. Show Categories In Sidebar Menu
343343
1. update ProductListScreen.js
344344
2. handle delete button

backend/routers/uploadRouter.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import express from 'express';
2+
import multer from 'multer';
3+
import { isAuth, isAdmin } from '../utils';
4+
5+
const storage = multer.diskStorage({
6+
destination(req, file, cb) {
7+
cb(null, 'uploads/');
8+
},
9+
filename(req, file, cb) {
10+
cb(null, `${Date.now()}.jpg`);
11+
},
12+
});
13+
14+
const upload = multer({ storage });
15+
const uploadRouter = express.Router();
16+
17+
uploadRouter.post('/', isAuth, isAdmin, upload.single('image'), (req, res) => {
18+
res.status(201).send({ image: `/${req.file.path}` });
19+
});
20+
export default uploadRouter;

backend/server.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import express from 'express';
22
import cors from 'cors';
33
import mongoose from 'mongoose';
44
import bodyParser from 'body-parser';
5-
import data from './data';
65
import config from './config';
76
import userRouter from './routers/userRouter';
87
import orderRouter from './routers/orderRouter';
98
import productRouter from './routers/productRouter';
9+
import uploadRouter from './routers/uploadRouter';
1010

1111
mongoose
1212
.connect(config.MONGODB_URL, {
@@ -23,6 +23,7 @@ mongoose
2323
const app = express();
2424
app.use(cors());
2525
app.use(bodyParser.json());
26+
app.use('/api/uploads', uploadRouter);
2627
app.use('/api/users', userRouter);
2728
app.use('/api/products', productRouter);
2829
app.use('/api/orders', orderRouter);

frontend/src/api.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,28 @@ export const updateProduct = async (product) => {
8080
}
8181
};
8282

83+
export const uploadProductImage = async (formData) => {
84+
try {
85+
const { token } = getUserInfo();
86+
const response = await axios({
87+
url: `${apiUrl}/api/uploads`,
88+
method: 'POST',
89+
headers: {
90+
Authorization: `Bearer ${token}`,
91+
'Content-Type': 'multipart/form-data',
92+
},
93+
data: formData,
94+
});
95+
if (response.statusText !== 'Created') {
96+
throw new Error(response.data.message);
97+
} else {
98+
return response.data;
99+
}
100+
} catch (err) {
101+
return { error: err.response.data.message || err.message };
102+
}
103+
};
104+
83105
export const signin = async ({ email, password }) => {
84106
try {
85107
const response = await axios({

frontend/src/srceens/ProductEditScreen.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
showMessage,
55
hideLoading,
66
} from '../utils';
7-
import { getProduct, updateProduct } from '../api';
7+
import { getProduct, updateProduct, uploadProductImage } from '../api';
88

99
const ProductEditScreen = {
1010
after_render: () => {
@@ -31,6 +31,22 @@ const ProductEditScreen = {
3131
document.location.hash = '/productlist';
3232
}
3333
});
34+
document
35+
.getElementById('image-file')
36+
.addEventListener('change', async (e) => {
37+
const file = e.target.files[0];
38+
const formData = new FormData();
39+
formData.append('image', file);
40+
showLoading();
41+
const data = await uploadProductImage(formData);
42+
hideLoading();
43+
if (data.error) {
44+
showMessage(data.error);
45+
} else {
46+
showMessage('Image uploaded successfully.');
47+
document.getElementById('image').value = data.image;
48+
}
49+
});
3450
},
3551
render: async () => {
3652
const request = parseRequestUrl();
@@ -63,6 +79,7 @@ const ProductEditScreen = {
6379
<input type="text" name="image" value="${
6480
product.image
6581
}" id="image" />
82+
<input type="file" name="image-file" id="image-file" />
6683
</li>
6784
<li>
6885
<label for="brand">Brand</label>

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"express": "^4.17.1",
2525
"express-async-handler": "^1.1.4",
2626
"jsonwebtoken": "^8.5.1",
27-
"mongoose": "^5.9.21"
27+
"mongoose": "^5.9.21",
28+
"multer": "^1.4.2"
2829
},
2930
"devDependencies": {
3031
"@babel/cli": "^7.10.3",

uploads/file.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)