sql >> Database >  >> NoSQL >> MongoDB

Afbeelding geretourneerd door REST API wordt altijd weergegeven als defect

Vermijd het terugsturen van met base64 gecodeerde afbeeldingen (meerdere afbeeldingen + grote bestanden + grote gecodeerde reeksen =zeer trage prestaties). Ik raad ten zeerste aan om een ​​microservice te maken die alleen afbeeldingsuploads en andere afbeeldingsgerelateerde get/post/put/delete-verzoeken afhandelt. Scheid het van uw hoofdtoepassing.

Bijvoorbeeld:

  • Ik gebruik multer om een ​​afbeeldingsbuffer te maken
  • Gebruik vervolgens scherp of fs om de afbeelding op te slaan (afhankelijk van het bestandstype)
  • Vervolgens stuur ik het bestandspad naar mijn controller om het in mijn database op te slaan
  • Vervolgens doet de front-end een GET-verzoek wanneer het probeert toegang te krijgen tot:http://localhost:4000/uploads/timestamp-randomstring-originalname.fileext

In eenvoudige bewoordingen werkt mijn microservice als een CDN, uitsluitend voor afbeeldingen.

Een gebruiker stuurt bijvoorbeeld een postverzoek naar http://localhost:4000/api/avatar/create met wat FormData:

Het passeert eerst enkele Express-middlewares:

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     

Druk dan op de avatars route:

routes/avatars.js

app.post(`/api/avatar/create`, requireAuth, saveImage, create);

Het passeert vervolgens een aantal gebruikersauthenticatie en gaat vervolgens door mijn saveImage middleware:

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())

Als het bestand is opgeslagen, stuurt het een req.file.path naar mijn create controleur. Dit wordt in mijn database opgeslagen als een bestandspad en als een afbeeldingspad (het avatarFilePath of /uploads/imagefile.ext wordt opgeslagen voor verwijderingsdoeleinden en de avatarURL of [http://localhost:4000]/uploads/imagefile.ext wordt opgeslagen en gebruikt voor het front-end GET-verzoek):

controllers/avatars.js (Ik gebruik Postgres, maar je kunt Mongo vervangen)

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(); 
        }

Wanneer de front-end vervolgens toegang probeert te krijgen tot de uploads map via <img src={avatarURL} alt="image" /> of <img src="[http://localhost:4000]/uploads/imagefile.ext" alt="image" /> , het wordt geserveerd door de 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);

Hoe het eruit ziet bij het loggen van verzoeken:

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

Wat de gebruiker ziet na een succesvol GET-verzoek:




  1. Apache HBase-regio splitsen en samenvoegen

  2. Hoe de arrayFilters-parameter werkt in MongoDB

  3. ServiceStack Redis, hoe de Lua-tabel als lijst te retourneren

  4. Nieuwe functies voor back-upbeheer en beveiliging voor MySQL en PostgreSQL:ClusterControl Release 1.6.2