美文网首页Nodejs
Section-8 项目实战之上传图片模块

Section-8 项目实战之上传图片模块

作者: 羽晞yose | 来源:发表于2019-08-21 00:20 被阅读0次

    Lesson-1 上传图片需求分析

    上传图片的需求场景

    • 用户头像
    • 封面图片
    • 问题和回答中的图片
    • 话题图片

    上传图片的功能点

    • 基础功能:上传图片、生成图片链接
    • 附加功能:限制上传图片的大小与类型、生成高中低三种分辨率的图片链接,生成CDN(内容分发网络)

    上传图片的技术方案

    • 阿里云 OSS 等云服务,推荐在生产环境中使用
    • 直接上传到服务器,不推荐在生产环境中使用

    Lesson-2 使用 koa-body 中间件获取上传的文件

    操作步骤

    • 安装 koa-body,替换 koa-bodyparser
    • 设置图片上传目录
    • 使用 postman 上传文件

    安装 koa-body,替换 koa-bodyparser

    执行 npm i koa-body -S
    卸载掉之前安装的 koa-bodyparser,执行 npm uninstall koa-bodyparser -S

    设置图片上传目录

    将代码中原来的bodyparser给替换掉,当前目录下(app文件夹)新增 public/uploads 文件夹,作为图片上传路径

    // index.js
    const koaBody = require('koa-body'); // 替换原本的 bodyparser
    const path = require('path'); // 因为上传目录需要填写路径,所以需要用到 node 自带的 path 组件
    
    app.use(koaBody({
        multipart: true, // 启用文件
        formidable: {
            uploadDir: path.join(__dirname, 'public/uploads'), // 上传路径
            keepExtensions: true // 保留拓展名
        }
    }));
    

    我们将上传的方法写到 home.js 中,因为现在已经不是 users 特有的请求方法了

    // controllers/home.js
    class HomeCtl {
        index (ctx) {
            ctx.body = "这是主页";
        }
        // 新增 upload 方法
        upload (ctx) {
            const file = ctx.request.files.file;
            ctx.body = {
                path: file.path
            };
        }
    }
    
    // routes/home.js
    const { index, upload } = require('../controllers/home');
    
    // 路由中添加 post 方法,并规定路径为upload
    router.post('/upload', upload);
    

    使用 postman 上传文件

    这里不废话了,直接按照下图设置,点body,key选择file,随便找一张图片点击send发生,成功将拿到上传的图片路径


    postman上传设置截图
    用此图纪念已经退网的虎牙主播 -- 喵九

    有玩王者并且有看虎牙的,应该认识这个主播吧,技术虽然菜,但颜值达到星秀级别,口头禅:哎哟欸,已经退网很久了,怀念她的小书包被一群人揍的情景,哈哈~


    Lesson-3 使用 koa-static 中间件生成图片链接

    操作步骤

    • 安装 koa-static
    • 设置静态文件目录
    • 生成图片链接

    koa-static

    执行 npm i koa-static -S 进行安装

    设置静态文件目录

    // index.js
    const koaStatic = require('koa-static');
    // 使用koa-static,设置当前目录下的 public 文件夹作为上传图片的存储文件夹(静态资源文件夹)
    app.use(koaStatic(path.join(__dirname, 'public')));
    

    生成图片链接

    这一步是要把上一节中图片的相对路径转化为可以直接通过http请求来访问的路径,那么需要拿到当前域名以及图片上传后的文件名,文件名需要借助node-path插件中的 basename() 方法,域名可以使用koa上下文环境中的 origin 属性(由于官网文档没锚点,请自行搜索),至于为什么可以直接使用 ctx.origin 而不是 ctx.request.origin,那是因为 request 有别名

    request别名
    // controllers/home.js
    const path = require('path');
    
    upload (ctx) {
        const file = ctx.request.files.file;
        const basename = path.basename(file.path);
        ctx.body = {
            url: `${ctx.origin}/uploads/${basename}` // ctx.origin -> localhost:3000
        };
    }
    
    请求结果截图

    Lesson-4 编写前端页面上传文件

    操作步骤

    • 编写上传文件的前端页面
    • 与后端接口联调测试

    编写上传文件的前端页面

    因为上一节我们已经使用了 koa-static 将 public 文件夹作为静态资源路径,koa-static 默认不指定文件的话,会直接去查找该文件夹下的 index.html 文件作为默认页,所以我们只需要在 public 下创建一个 uploads.html 文件,就能直接通过浏览器访问该文件,有兴趣可以阅读该简短文章 分析koa-static的源码

    // public/uploads.html
    <form action="/upload" enctype="multipart/form-data" method="POST">
        <input type="file" name="file">
        <button type="submit">上传</button>
    </form>
    

    与后端接口联调测试

    这里其实就是直接测试上传文件是否成功,看一下文件夹中是否图片上传成功即可。因为我们是上传图片,所以需要对文件类型进行筛选,操作也很简单,只需要在 input 中指定一下 accept 属性即可,有三种格式,image/jpg, image/png || .jpg, .png || image/*,任君选择

    <input type="file" name="file" accept="image/*">
    

    Lesson-5 个人资料需求分析

    浏览知乎个人资料页

    这个就不演示了吧,直接去知乎进入个人资料页

    个人资料功能点

    • 不同类型(如字符串、数组)的属性
    • 字段过滤

    Lesson-6 个人资料的 schema 设计

    操作步骤

    • 分析个人资料的数据结构
    • 设计个人资料的 schema

    分析&设计 schema

    // models/users.js
    const mongoose = require('mongoose');
    
    const { Schema, model } = mongoose;
    
    const userSchema = new Schema({
        __v: { type: Number, select: false },
        name: { type: String, required: true },
        password: { type: String, required: true, select: false },
        avatar_url: { type: String }, // 用户头像
        gender: { type: String, enum: ['male', 'female'], default: 'male', required: true }, // enum 可枚举,性别
        headline: { type: String }, // 一句话简介
        locations: { type: [{ type: String }] }, // 可枚举的字符串数组,居住地
        business: { type: String }, // 公司
        employments: {  // 职业经历
            type: [{
                company: { type: String },
                job: { type: String }
            }]
        },
        educations: { // 教育经历
            type: [{
                school: { type: String },
                major: { type: String },
                diploma: { type: Number, enum: [1, 2, 3, 4, 5] },
                entrance_year: { type: Number },
                graduation_year: { type: Number }
            }]
        }
    });
    
    // user代表集合,导出的是一个类
    module.exports = model('user', userSchema);
    

    相关文章

      网友评论

        本文标题:Section-8 项目实战之上传图片模块

        本文链接:https://www.haomeiwen.com/subject/iwfjsctx.html