首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >antdesign + koa 实现图片上传

antdesign + koa 实现图片上传

作者头像
用户4793865
发布于 2023-01-12 08:25:08
发布于 2023-01-12 08:25:08
92800
代码可运行
举报
文章被收录于专栏:前端小菜鸡yym前端小菜鸡yym
运行总次数:0
代码可运行

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战

我们今天实现一下图片上传,前端用到的是antdesign中的文件上传,后端是自己封装的node的koa框架。

这个过程大致是:前端将图片提交给后端,后端将其存入后端项目的文件夹中,然后将图片所在路径返回给前端,前端得到图片路径后将图片路径再提交到后端保存的接口,存入数据库中

后端

在主文件中添加配置

我这个项目的配置文件在 app/index.js

图片上传的路径在 app/public/uploads

插件

koa-static

作用:声明一个静态文件夹,可以供上传图片找到。

安装:npm install koa-static

npm网址 : https://www.npmjs.com/package/koa-static

用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 引入 koa-static
const koaStatic = require('koa-static');
// 引入koa
const Koa = require('koa');
// 实例化koa对象
const app = new Koa();
// 挂载
app.use(koaStatic(path.join(__dirname, 'public')))

koa-body

作用:配置koa的body体接收格式

安装:npm install koa-body

npm网址:https://www.npmjs.com/package/koa-body

用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const Koa = require('koa');
const koaBody = require('koa-body');
 
const app = new Koa();
 
app.use(koaBody());
app.use(ctx => {
  ctx.body = `Request Body: ${JSON.stringify(ctx.request.body)}`;
});

我们的配置 app/index.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const Koa = require('koa')
const KoaBody = require('koa-body')
const path = require('path')
const koaStatic = require('koa-static')
const cors = require('koa2-cors');
const app = new Koa()
// 必须是一个函数
app.use(cors());
// 1. 文件上传到的路径 __diname是当前index.js所在的位置 public文件夹跟其同级
app.use(koaStatic(path.join(__dirname, 'public')))
// 2.在注册路由前注册
app.use(KoaBody({
    multipart: true,
    uploadDir: path.join(__dirname, 'uploads'),
    maxFileSize: 200 * 1024 * 1024,    // 设置上传文件大小最大限制,默认2M
    // 保留文件扩展名
    // keepExtensions: true,

}))

module.exports = app

添加路由

在router文件下的client.route.js中添加路由

这样添加后我们之后访问的路径就是 http://localhost:80001/client/Upload

Controller

在我们的controller文件夹下的client.controller.js中写入方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 图片上传
    async Upload(ctx,next){
        // 前端的name要于此出 file相同 。 如果叫 img 前端组件也需要name='img'
        const file = ctx.request.files.file; // 获取上传文件

        console.log(ctx.request,'file')
        // 创建可读流
        const reader = fs.createReadStream(file.path);
        const random_num = random(16)
        const fileName = random_num+'.'+file.name.split('.')[1]
        let filePath = path.join(__dirname, '../app/public/uploads/') + `/${fileName}`;
        
        // 创建可写流
        const upStream = fs.createWriteStream(filePath);
        // 可读流通过管道写入可写流
        reader.pipe(upStream);
        最后将图片的存储路径返回
        ctx.body = {'url':`${ctx.origin}/uploads/${fileName}`}     
    }

前端

antdesgin对应的文档 :https://ant.design/components/upload-cn/

我们先看组件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Button, Input, Drawer, Form, Select, Tag, Upload, message } from 'antd';
      <Upload
              // 对应后端的 ctx.request.files.file
              name="file"
              listType="picture-card"
              className="avatar-uploader"
              showUploadList={false}
              action="/api/client/Upload"
              beforeUpload={beforeUpload}
              onChange={handleChange}
            >
              {imageUrl ? (
                <img src={imageUrl} alt="avatar" style={{ width: '100%', marginTop: '10px' }} />
              ) : (
                <div>
                  {loading ? <LoadingOutlined /> : <PlusOutlined />}
                  <div style={{ marginTop: 8 }}>Upload</div>
                </div>
              )}
            </Upload>

首先,注意name要和后端接收的名字对应上

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 后端对应代码
const file = ctx.request.files.file; // 获取上传文件

listType

上传列表的内建样式,支持三种基本样式 textpicture 和 picture-card 他们的样式也不相同。可以去官网具体看。

showUploadList

是否展示文件列表, 可设为一个对象,用于单独设定 showPreviewIconshowRemoveIconshowDownloadIconremoveIcon 和 downloadIcon

action

也就是 form表单写法的action方法,即提交对应的的后端路径。这里的 /api代理到了 localhost:8001

然后看用到的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 // 图片地址
  const [imageUrl, setImageUrl] = useState<string>();
  // 加载
  const [loading, setLoading] = useState(false);
  // 上传前
  const beforeUpload = file => {
    // 图片格式
    const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
    if (!isJpgOrPng) {
      message.error('You can only upload JPG/PNG file!');
    }
    const isLt2M = file.size / 1024 / 1024 < 2;
    if (!isLt2M) {
      message.error('Image must smaller than 2MB!');
    }
    return isJpgOrPng &amp;&amp; isLt2M;
  };
  // 转为base64
  const getBase64 = (img: Blob, callback: any) => {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result));
    reader.readAsDataURL(img);
  };
  // 上传图片
  const handleChange = (info: any) => {
    console.log(info.file, 'info');
    if (info.file.status === 'uploading') {
      setLoading(true);
      return;
    }
    if (info.file.status === 'done') {
      getBase64(info.file.originFileObj, (imageUrl: any) => {
        setImageUrl(imageUrl);
        setSubmitParams({ ...submitParams, cover: info.file.response.url });
        setLoading(false);
      });
    }
  };
  const handleUpload = e => {
    const file = e.target.files[0];
    console.log(file, 'hand');
  };

beforeUpload

图片提交前的处理函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 上传前
  const beforeUpload = file => {
    // 图片格式
    const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
    if (!isJpgOrPng) {
      message.error('You can only upload JPG/PNG file!');
    }
    const isLt2M = file.size / 1024 / 1024 < 2;
    if (!isLt2M) {
      message.error('Image must smaller than 2MB!');
    }
    return isJpgOrPng &amp;&amp; isLt2M;
  };

handleChange

上传图片

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 上传图片
  const handleChange = (info: any) => {
    console.log(info.file, 'info');
    // 上传过程中将loading状态设为true
    if (info.file.status === 'uploading') {
      setLoading(true);
      return;
    }
    // 上传完成 
    if (info.file.status === 'done') {
      getBase64(info.file.originFileObj, (imageUrl: any) => {
      // 设置图片路径
        setImageUrl(imageUrl);
        // 设置提交参数 我这个页是个大表单 图片只是一部分。我们要把上传图片接口返回的图片的
        // 存储路径返回
        setSubmitParams({ ...submitParams, cover: info.file.response.url });
        //上传完成将loading状态设为true
        setLoading(false);
      });
    }
  };

实现效果

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
软件建模与文档:架构师怎样绘制系统架构蓝图?
首先,请你设想这样一个场景:如果公司安排你做架构师,要你在项目开发前期进行软件架构设计,你该如何开展你的工作?如何输出你的工作成果?如何确定你的设计是否满足用户需求?你是否有把握最后交付的软件是满足要求的?是否有把握让团队每个工程师清楚自己的职责范围并有效地完成开发工作……
小熊学Java
2023/11/27
7120
软件建模与文档:架构师怎样绘制系统架构蓝图?
优秀的架构师,如何画一手好的架构蓝图?
今天我们来了解一些关于软件设计文档的基础知识,这样你在学习后面的具体案例时,就能更加清楚地理解文档是基于什么方式来组织的了。
码猿技术专栏
2023/12/26
6220
优秀的架构师,如何画一手好的架构蓝图?
解读架构师的核心工作内容
很多做软件开发同学的梦想都是成为一名架构师,而架构师的核心工作就是做好软件设计。软件设计是软件开发过程中的一个重要环节,那么如何进行软件设计,其输出标准又是什么呢?软件设计过程中,如何和各个相关方沟通,使软件设计能同时满足用户的功能需求和非功能需求,并降低公司的开发成本?
架构之家
2022/07/12
7360
解读架构师的核心工作内容
软件设计实践:如何使用UML完成一个设计文档?
在上一篇文章中,我们讨论了为什么要建模,以及建模的 4+1 视图模型,4+1 视图模型很好地向我们展示了如何对一个软件的不同方面用不同的模型图进行建模与设计,以完整描述一个软件的业务场景与技术实现。但是软件开发是有阶段性的,在不同的开发阶段用不同的模型图描述业务场景与设计思路,在不同阶段输出不同的设计文档,对于现实的开发更有实践意义。
小马哥学JAVA
2022/11/14
1.6K0
软考高级:UML 图 结构图、行为图和交互图 概念和题目
UML(统一建模语言)是一种用于软件系统分析和设计的标准语言,它通过提供标准化的图形表示方法来帮助软件开发者定义、可视化、构建和文档化软件系统的各个部分。UML图形大体上可以分为三大类:结构图、行为图和交互图。每一类图又包括了几种特定的图形,用于展示系统的不同方面。
明明如月学长
2024/05/24
5060
软考高级:UML 图 结构图、行为图和交互图 概念和题目
软件设计必备的 UML,你会吗?
UML 是统一建模语言(英语:Unified Modeling Language,缩写 UML)的简称,它是一种由一整套图表组成的标准化建模语言,用于帮助系统开发人员来说明,可视化,构建和记录软件系统的产出。用人话说 UML 就是用图形符号帮助我们描述系统和设计系统的语言工具。
闻人的技术博客
2020/06/17
3.3K0
软件设计必备的 UML,你会吗?
软考高级:UML 静态图(机构图)、动态图(行为图)概念和例题
UML(统一建模语言)是一种标准的建模语言,用于软件系统的规划、设计与文档化。UML中的图分为两大类:静态图和动态图。静态图表示系统的静态结构,动态图表示系统的行为和交互。以下是静态图和动态图的基本概念和类型。
明明如月学长
2024/05/24
6710
软考高级:UML 静态图(机构图)、动态图(行为图)概念和例题
架构图、用例图、流程图、时序图、类图
用例图:用例图是指由参与者(Actor)、用例(Use Case),边界以及它们之间的关系构成的用于描述系统功能的视图。是系统的蓝图。
看、未来
2020/10/09
15.6K0
架构图、用例图、流程图、时序图、类图
【UML】统一建模语言
参考博客:https://blog.csdn.net/unique_perfect/article/details/104989118
鸡先生
2022/10/29
9630
【UML】统一建模语言
UML与系统架构图:找到最佳表示方法
UML(统一建模语言)是一种广泛用于软件工程的建模语言。它提供了一套丰富的图示工具,用于描述软件系统的各个方面。那么,在构建系统架构图时,UML中有哪些视图可以被有效地应用呢?我们在这篇文章里会深入探讨这个问题。
运维开发王义杰
2023/09/19
6430
UML与系统架构图:找到最佳表示方法
UML各种图
UML(Unified Modeling Language)是一种统一建模语言,为面向对象开发系统的产品进行说明、可视化、和编制文档的一种标准语言。下面将对UML的九种图+包图的基本概念进行介绍以及各个图的使用场景。
用户3467126
2021/09/03
1.5K0
UML各种图
UML
UML 中包括九种图:用例图、类图、对象图、状态图、时序图、协作图、活动图、组件图、 配置图。
似水的流年
2021/11/30
9140
如何画好架构图
本文作者阿里巴巴技术专家三画,分享了自己和团队在画好架构图方面的理念和经验,首发于阿里内部技术分享平台,阿里巴巴中间件授权转载,梓敬、鹏升和余乐对此文亦有贡献。
程序猿DD
2019/05/10
2.1K1
如何画好架构图
如何画好一张架构图?
在上一篇文章《4款亲测好用的开发画图工具》中,有读者在后台留言提到想了解如何画好一张架构图?本文作者从架构图的目的、怎样的架构图是好的架构图、如何画好架构图,以及各类经典架构图的分类和示例都做了详尽解析,是一篇不可多得的干货文章,建议点赞收藏!
腾讯云开发者
2024/03/20
4.9K0
如何画好一张架构图?
总结如何画一手好的架构图!!!
你是否被大厂展示的五花八门,花花绿绿的架构设计图所深深吸引,当我们想用几张图来介绍下业务系统,是不是对着画布不知从何下手?作为技术扛把子的筒子们是不是需要一张图来描述系统,让系统各个参与方都能看的明白?如果有这样的困惑,本文将介绍一些画图的方法论,让技术图纸更加清晰。
测试开发技术
2022/12/27
9641
总结如何画一手好的架构图!!!
画好架构图,是进阶的必经之路
本文作者阿里巴巴技术专家三画,分享了自己和团队在画好架构图方面的理念和经验,首发于阿里内部技术分享平台,阿里巴巴中间件授权转载,梓敬、鹏升和余乐对此文亦有贡献。
二哥聊运营工具
2021/12/17
6991
画好架构图,是进阶的必经之路
软件工程的那些图
小编最近在画各种图,正好和大家一起复习一下。说到软件工程,不得不说一个语言:UML,即Unified Modeling Language ,统一建模语言,我们的群网盘上有该工具的下载哦。链接:http://pan.baidu.com/s/1gfE6rkf 密码:0dv8。虽然这是标准的作图工具,但是并不是很好看,有的时候我们也会使用Visio来代替。UML主要支持两大类的模型,静态模型图和动态模型图。
一头小山猪
2020/04/10
1.1K0
七、 软件工程(二)
利用用例和用例图表示需求,从用例模型中提炼形成领域模型,用例的实现可以用交互图表示,从领域模型和用例图形成类图,用包图和类图形成体系结构图
堕落飞鸟
2022/01/10
7240
在线免费制作架构图
Freedgo Design 是一in款在线绘制专业图形的网站。Freedgo Design可以绘制各种类型的图形,针对业务逻辑的流程图,软件设计ER模板,工作流,各种云平台的系统部署架构图包括阿里云、AWS云、腾讯云、Oracle、Asure云、IBM云平台等。
用户1963364
2019/05/20
67.1K0
在线免费制作架构图
【UML建模】(1) UML建模的初了解
UML (Unified Modeling Language)是一种通用的可视化的建模语言,可以用来描述、可视化、构造和文档化软件密集型系统的各种工件。它不是一种程序设计语言。UML 是独立于过程的,它可以在软件生命周期的各个阶段运用,不过主要应用于软件开发的设计与分析阶段。
码农飞哥
2022/03/31
9230
【UML建模】(1) UML建模的初了解
相关推荐
软件建模与文档:架构师怎样绘制系统架构蓝图?
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档