This is the fifth day of my participation in the August Wen Challenge.More challenges in August

Previous articleFinished the comment, reply to the comment, query the comment, delete the comment

  • After creating the label,
  • Assign labels to the dynamic
  • Uploading user profile pictures
  • Upload dynamic pictures

Create label tables for multi-table queries

CREATE TABLE IF NOT EXISTS `label`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(10) NOT NULL UNIQUE,
	createAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
	updateAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Copy the code

Finish creating the label

//label.router.js

const Router = require('koa-router')

const labelRouter = new Router({prefix: "/label"})

const {
    verifyAuth    // Verify user login
} = require('.. /middleware/auth.middleware')

const {
    create
} = require('.. /controller/label.controller')

labelRouter.post('/', verifyAuth, create)

module.exports = labelRouter
Copy the code

Process the data

//label.controller.js

const service = require('.. /service/label.service.js')

class labelController {
    async create(ctx, next) {
        const {name} = ctx.request.body

        const result = await service.create(name)

        ctx.body = result
    }
}

module.exports = new labelController()
Copy the code

Add to database

//label.service.js

const connection = require(".. /app/database");

class LabelService {
    async create(name) {
        try {
          const statement = `INSERT INTO label (name) VALUES (?) `;
    
          const [result] = await connection.execute(statement, [name]);
    
          return result;
        } catch (error) {
          console.log(error); }}}module.exports = new LabelService();
Copy the code

test

Assign labels to the dynamic

//moment.router.js

const Router = require('koa-router')

const momentRouter = new Router({prefix: '/moment'})

const {
    verifyAuth,
    verifyPermission
} = require('.. /middleware/auth.middleware')

const {
    addLabels
} = require('.. /controller/moment.controller')

const {
    verifyLabelExists
} = require('.. /middleware/label.middleware')

momentRouter.post("/:momentId/labels", verifyAuth, verifyPermission("moment"), verifyLabelExists, addLabels)

module.exports = momentRouter
Copy the code

Check whether the label passed by the user exists

// label.middleware.js

const service = require('.. /service/label.service')

const verifyLabelExists = async (ctx, next) => {
    // Fetch the label to add
    const {labels} = ctx.request.body
    console.log(labels);

    // Check whether the tag exists
    const newLabels = []
    for(let name of labels){
        const labelResult = await service.getLabelByName(name)
        const label = {name}
        if(! labelResult) {// Create label data
            const result = await service.create(name)
            label.id = result.insertId
        }else {
            label.id = labelResult.id
        }
        newLabels.push(label)
    }

    ctx.labels = newLabels
    await next()
}

module.exports = {
    verifyLabelExists
}
Copy the code

The label and dynamic ID are obtained and passed to the database processing file

//moment.controller.js

const momentService = require(".. /service/moment.service");

class MomentController {
    async addLabels(ctx, next) {
        // 1. Obtain the label and dynamic ID
        const { labels } = ctx;
        const { momentId } = ctx.params;

        // 2. Add all the labels
        for (let label of labels) {
          // 2.1. Check whether the label has been associated with the dynamic
          const isExist = await momentService.hasLabel(momentId, label.id);
          if(! isExist) {await momentService.addLabel(momentId, label.id);
          }
        }

        ctx.body = "Dynamic label added successfully ~"; }}module.exports = new MomentController();
Copy the code

Get the data, process it

//moment.service.js

const connection = require(".. /app/database");

class MomentService {
    
    // Determine whether the dynamic owns the label
    async hasLabel(momentId, labelId) {
        const statement = ` SELECT * FROM moment_label WHERE moment_id = ? AND label_id = ? `;
        const [result] = await connection.execute(statement, [momentId, labelId]);
        return result[0]?true: false;
      }
    // Add dynamic labels
      async addLabel(momentId, labelId) {
        const statement = `INSERT INTO moment_label (moment_id, label_id) VALUES (? ,?) ; `;
        const [result] = await connection.execute(statement, [momentId, labelId]);
        returnresult; }}module.exports = new MomentService();
Copy the code

Upload the picture

//file.router.js

const Router = require('koa-router')

const filRouter = new Router({prefix: '/upload'})

const {
    verifyAuth  // Verify login
} =require('.. /middleware/auth.middleware')

const {
    avatarHandler
} = require('.. /middleware/file.middleware')

const {
    saveAvatarInfo
} = require('.. /controller/file.controller')

// Upload profile picture
filRouter.post('/avatar', verifyAuth, avatarHandler, saveAvatarInfo)

module.exports = filRouter
Copy the code

implementationavatarHandlerThe middlewarenpm install koa-multer

//file.middleware.js

const Multer = require("koa-multer");

const avatarUpLoad = Multer({
  dest: "./uploads/avatar".// Save the uploaded image to a location
});

const avatarHandler = avatarUpLoad.single("avatar");

module.exports = {
  avatarHandler
};
Copy the code

Get the information about the uploaded image and save it to the database

//file.controller.js

const fileService = require(".. /service/file.service");
const userService = require('.. /service/user.service')
const {APP_HOST, APP_PORT} = require('.. /app/config')

class FileController {
    async saveAvatarInfo(ctx, next) {
        // Get image information
        const { mimetype, filename, size } = ctx.req.file;
        const { id } = ctx.user;

        // Save the image information to the database
        const result = await fileService.createAvatar(filename, mimetype, size, id);

        // Save the image address to user
        const avatarUrl = `${APP_HOST}:${APP_PORT}/users/${id}/avatar`
        console.log(avatarUrl);   / / http://localhost:8080/users/ user id/avatars
        await userService.updateAvatarUrlById(avatarUrl, id)

        // Return the result
        ctx.body = "Avatar uploaded successfully"; }}module.exports = new FileController();
Copy the code

Access to image

//user.router.js

const Router = require('koa-router')

const userRouter = new Router()

const {
    avatarInfo
} = require(".. /controller/user.controller")

// Get the avatar
userRouter.get('/users/:userId/avatar', avatarInfo)

module.exports = userRouter
Copy the code

Setting image Information

//user.controller.js

const fs = require('fs')

const userService = require(".. /service/user.service");
const fileService = require(".. /service/file.service");
const { AVATAR_PATH } = require(".. /constants/file-path");

class UserController {
  async avatarInfo(ctx, next) {
    / / get userId
    const { userId } = ctx.params;
    // Query the profile picture
    const avatarInfo = await fileService.getAvatarByUserId(userId);
    console.log(avatarInfo); -->
                `BinaryRow { id: 1, filename: '48b2d8e3740441294e57c91750f59e99', mimetype: 'image/jpeg', size: 98258, user_id: 2, createAt: 2021-08-17T08:11:53.000z, updateAt: 2021-08-17T08:11:53.000z}
 
    // Provide image information
    ctx.response.set('content-type', avatarInfo.mimetype)  // Tell the browser that this is an image
    ctx.body = fs.createReadStream(`${AVATAR_PATH}/${avatarInfo.filename}`); }}module.exports = new UserController();
Copy the code

The query image

//file.service.js

const connection = require(".. /app/database");

class FileService {
    async getAvatarByUserId(userId) {
        try {
          const statemnet = `SELECT * FROM avatar WHERE user_id = ? `;

          const [result] = await connection.execute(statemnet, [userId]);

          return result[0];
        } catch (error) {
          console.log(error); }}}module.exports = new FileService();
Copy the code

Upload dynamic pictures

//file.router.js

const Router = require('koa-router')

const filRouter = new Router({prefix: '/upload'})

const {
    verifyAuth  // Verify login
} =require('.. /middleware/auth.middleware')

const {
    pictureHandler
} = require('.. /middleware/file.middleware')

const {
    savePictureInfo
} = require('.. /controller/file.controller')

// Upload the image
filRouter.post('/picture', verifyAuth, pictureHandler, savePictureInfo)

module.exports = filRouter
Copy the code

Get uploaded picture

//file.middleware.js

const Multer = require("koa-multer");

const pictureUpload = Multer({
  dest: "./uploads/picture"});const pictureHandler = pictureUpload.array("picture".9);

module.exports = {
  pictureHandler
};
Copy the code

Setting image Information


const fileService = require(".. /service/file.service")

class FileController {
    async savePictureInfo(ctx, next) {
        // Get information
        const files = ctx.req.files
        const {id} = ctx.user
        const {momentId} = ctx.query

        // Save to database
        for(let file of files) {
          const {filename, mimetype, size} = file

          await fileService.createFile(filename, mimetype, size, id, momentId)
        }

        ctx.body = "Dynamic illustration uploaded successfully"}}module.exports = new FileController();
Copy the code

The database handles dynamic mapping

//file.service.js

const connection = require(".. /app/database");

class FileService {
    async createFile(filename, mimetyep, size, userId, momentId) {
    try {
      const statement = `INSERT INTO file (filename, mimetype, size, user_id, moment_id) VALUES (? ,? ,? ,? ,?) `;

      const [result] = await connection.execute(statement, [
        filename,
        mimetyep,
        size,
        userId,
        momentId,
      ]);

      return result;
    } catch (error) {
      console.log(error); }}}module.exports = new FileService();
Copy the code

Get dynamic illustrations

//moment.router.js

const Router = require('koa-router')

const momentRouter = new Router({prefix: '/moment'})

const {
    fileInfo
} = require('.. /controller/moment.controller')

// dynamic mapping
momentRouter.get('/images/:filename', fileInfo)

module.exports = momentRouter
Copy the code
const fs = require("fs");

const fileService = require(".. /service/file.service");
const momentService = require(".. /service/moment.service");
const { PICTURE_PATH } = require(".. /constants/file-path");

class MomentController {
    async fileInfo(ctx, next) {
        try {
          let { filename } = ctx.params;
          
          const fileInfo = await fileService.getFileByFilename(filename);
        
          ctx.response.set("content-type", fileInfo.mimetype);
          
          ctx.body = fs.createReadStream(`./uploads/picture/${filename}`);
        } catch (error) {
          console.log(error); }}}module.exports = new MomentController();
Copy the code
const connection = require(".. /app/database");

class FileService {
    async getFileByFilename(filename) {
         const statement = `SELECT * FROM file WHERE filename = ? `

         const [result] = await connection.execute(statement, [filename])

         return result[0]; }}module.exports = new FileService();
Copy the code

Finally, we also need to modify the dynamic query, because users have avatars, they need to query together

//moment.service.js

const connection = require(".. /app/database");

class MomentService {
    // a single dynamic query for this
    async getMomentById(id) {
        const statement = ` SELECT m.id id, m.content content, m.createAt createTime, m.updateAt updateTime, JSON_OBJECT('id', u.id, 'name', u.name, 'avatarUrl', u.avatar_url) author, IF(COUNT(l.id),JSON_ARRAYAGG( JSON_OBJECT('id', l.id, 'name', l.name) ),NULL) labels, (SELECT IF(COUNT(c.id),JSON_ARRAYAGG( JSON_OBJECT('id', c.id, 'content', c.content, 'commentId', c.comment_id, 'createTime', c.createAt, 'user', JSON_OBJECT('id', cu.id, 'name', cu.name, 'avatarUrl', cu.avatar_url)) ),NULL) FROM comment c LEFT JOIN user cu ON c.user_id = cu.id WHERE m.id = c.moment_id) comments, (SELECT JSON_ARRAYAGG(CONCAT('http://localhost:8080/moment/images/', file.filename)) FROM file WHERE m.id = file.moment_id) images FROM moment m LEFT JOIN user u ON m.user_id = u.id LEFT JOIN moment_label ml ON m.id = ml.moment_id LEFT JOIN label l ON ml.label_id = l.id WHERE m.id = ? GROUP BY m.id; `;

        const [result] = await connection.execute(statement, [id]);

        return result[0]; }}module.exports = new MomentService();
Copy the code
//moment.service.js

const connection = require(".. /app/database");

class MomentService {
    // Multiple dynamic queries for this
    async getMomentList(offset, size) {
    const statement = ` SELECT m.id id, m.content content, m.createAt createTime, m.updateAt updateTime, JSON_OBJECT('id', u.id, 'name', u.name) author, (SELECT COUNT(*) FROM comment c WHERE c.moment_id = m.id) commentCount, (SELECT COUNT(*) FROM moment_label ml WHERE ml.moment_id = m.id) labelCount, (SELECT JSON_ARRAYAGG(CONCAT('http://localhost:8080/moment/images/', file.filename)) FROM file WHERE m.id = file.moment_id) images FROM moment m LEFT JOIN user u ON m.user_id = u.id LIMIT ? And?; `;

    const [result] = await connection.execute(statement, [offset, size]);

    returnresult; }}module.exports = new MomentService();
Copy the code

The project address, interested partners can go to download, have a try oh