Tránh gửi lại hình ảnh được mã hóa base64 (nhiều hình ảnh + tệp lớn + chuỗi mã hóa lớn =hiệu suất rất chậm). Tôi thực sự khuyên bạn nên tạo một microservice chỉ xử lý tải lên hình ảnh và bất kỳ yêu cầu get / post / put / delete liên quan đến hình ảnh nào khác. Tách nó khỏi ứng dụng chính của bạn.
Ví dụ:
- Tôi sử dụng multer để tạo bộ đệm hình ảnh
- Sau đó, sử dụng sharp hoặc fs để lưu hình ảnh (tùy thuộc vào loại tệp)
- Sau đó, tôi gửi đường dẫn tệp đến bộ điều khiển để được lưu vào DB của tôi
- Sau đó, giao diện người dùng thực hiện yêu cầu GET khi nó cố gắng truy cập:
http://localhost:4000/uploads/timestamp-randomstring-originalname.fileext
Nói một cách dễ hiểu, microservice của tôi hoạt động giống như một CDN chỉ dành cho hình ảnh.
Ví dụ:người dùng gửi yêu cầu đăng bài tới http://localhost:4000/api/avatar/create
với một số FormData:
Đầu tiên nó đi qua một số phần mềm trung gian Express:
libs / middlewares.js
...
app.use(cors({credentials: true, origin: "http://localhost:3000" })) // allows receiving of cookies from front-end
app.use(morgan(`tiny`)); // logging framework
app.use(multer({
limits: {
fileSize: 10240000,
files: 1,
fields: 1
},
fileFilter: (req, file, next) => {
if (!/\.(jpe?g|png|gif|bmp)$/i.test(file.originalname)) {
req.err = `That file extension is not accepted!`
next(null, false)
}
next(null, true);
}
}).single(`file`))
app.use(bodyParser.json()); // parses header requests (req.body)
app.use(bodyParser.urlencoded({ limit: `10mb`, extended: true })); // allows objects and arrays to be URL-encoded
...etc
Sau đó, truy cập avatars
tuyến đường:
route / avatars.js
app.post(`/api/avatar/create`, requireAuth, saveImage, create);
Sau đó, nó chuyển qua một số xác thực người dùng, sau đó đi qua saveImage
của tôi phần mềm trung gian:
services / saveImage.js
const createRandomString = require('../shared/helpers');
const fs = require("fs");
const sharp = require("sharp");
const randomString = createRandomString();
if (req.err || !req.file) {
return res.status(500).json({ err: req.err || `Unable to locate the requested file to be saved` })
next();
}
const filename = `${Date.now()}-${randomString}-${req.file.originalname}`;
const filepath = `uploads/${filename}`;
const setFilePath = () => { req.file.path = filepath; return next();}
(/\.(gif|bmp)$/i.test(req.file.originalname))
? fs.writeFile(filepath, req.file.buffer, (err) => {
if (err) {
return res.status(500).json({ err: `There was a problem saving the image.`});
next();
}
setFilePath();
})
: sharp(req.file.buffer).resize(256, 256).max().withoutEnlargement().toFile(filepath).then(() => setFilePath())
Nếu tệp được lưu, tệp sẽ gửi req.file.path
vào create
của tôi bộ điều khiển. Điều này được lưu vào DB của tôi dưới dạng đường dẫn tệp và đường dẫn hình ảnh (avatarFilePath
hoặc /uploads/imagefile.ext
được lưu cho mục đích xóa và avatarURL
hoặc [http://localhost:4000]/uploads/imagefile.ext
được lưu và sử dụng cho yêu cầu GET của giao diện người dùng):
controller / avatar.js (Tôi đang sử dụng Postgres, nhưng bạn có thể thay thế cho Mongo)
create: async (req, res, done) => {
try {
const avatarurl = `${apiURL}/${req.file.path}`;
await db.result("INSERT INTO avatars(userid, avatarURL, avatarFilePath) VALUES ($1, $2, $3)", [req.session.id, avatarurl, req.file.path]);
res.status(201).json({ avatarurl });
} catch (err) { return res.status(500).json({ err: err.toString() }); done();
}
Sau đó, khi giao diện người dùng cố gắng truy cập vào uploads
thư mục qua <img src={avatarURL} alt="image" />
hoặc <img src="[http://localhost:4000]/uploads/imagefile.ext" alt="image" />
, nó được phục vụ bởi microservice:
libs / server.js
const express = require("express");
const path = app.get("path");
const PORT = 4000;
//============================================================//
// EXPRESS SERVE AVATAR IMAGES
//============================================================//
app.use(`/uploads`, express.static(`uploads`));
//============================================================//
/* CREATE EXPRESS SERVER */
//============================================================//
app.listen(PORT);
Nó trông như thế nào khi yêu cầu ghi nhật ký:
19:17:54 INSERT INTO avatars(userid, avatarURL, avatarFilePath) VALUES ('08861626-b6d0-11e8-9047-672b670fe126', 'http://localhost:4000/uploads/1536891474536-k9c7OdimjEWYXbjTIs9J4S3lh2ldrzV8-android.png', 'uploads/1536891474536-k9c7OdimjEWYXbjTIs9J4S3lh2ldrzV8-android.png')
POST /api/avatar/create 201 109 - 61.614 ms
GET /uploads/1536891474536-k9c7OdimjEWYXbjTIs9J4S3lh2ldrzV8-android.png 200 3027 - 3.877 ms
Những gì người dùng nhìn thấy khi yêu cầu GET thành công: