egg后端+Antd 上传图片到后端和读取图片在前端显示

在做项目过程中,常常会涉及保存图片的功能,以下是我使用egg.js+Antd完成的保存单张图片、从后端将图片传给前端的代码。

egg代码

项目思路:

  1. 将前端获得的图片存放在egg项目的某个文件夹中
  2. 将图片的地址存入数据库中
  3. 读取图片时,将数据库中的图片路径取出,转为base64格式传给前端
  4. 前端将base64转为图片显示

以下是我省去将图片路径写入数据库的步骤的代码。

在egg的控制器中某个js文件写入以下代码

//  app/controller/uploadImg.js
const Controller = require('egg').Controller;
//文件存储
const fs = require('fs');
const path = require('path');
const awaitWriteStream = require('await-stream-ready').write;
const imgBaseUrl = 'app/public/testUploadImg';//这是我的图片存放位置

class HomeController extends Controller {
    //  上传单张头像图片
    async uploadImg() {
        const ctx = this.ctx;
        //获取前端的文件流
        try {
            const stream = await ctx.getFileStream();
            // let uid=stream.fieldname;
            let time = Date.now();
            const filename = time + ".jpg";//文件名应该是有随机成分的且不能相同
            // 同步读取文件
            let files = fs.readdirSync(imgBaseUrl);//读取该文件夹
            let target = path.join(imgBaseUrl, filename);
            const writeStream = fs.createWriteStream(target);// 生成一个文件写入 文件流
            try {
                // 异步把文件流 写入
                await awaitWriteStream(stream.pipe(writeStream));
            } catch (err) {
                // 如果出现错误,关闭管道
                await sendToWormhole(stream);
                throw err;
            }
            //存图片路径到数据库中
            //我的图片路径是'app/public/testUploadImg'+filename;
            //在这里可以将图片的路径存入到自己对应的想要存入的表中
            //因为egg提供的数据库操作渠道较多,此处代码省略
            //===============================

            return ctx.body = {
                status: 1,
            };
        } catch (error) {
            console.log(error);
            ctx.body = {
                status: 0
            };
        }
    }

    //获取图片
    async getImg() {
        const ctx = this.ctx;
        try {
        //这里将文件夹下的所有图片都读出了,实际上应该是从数据库中得到图片路径
        //在从imgBaseUrl中获得相应的图片完整路径,使用fs.readFileSync("完整的图片路径", 'base64');将图片转为base64格式,
            let files = fs.readdirSync(imgBaseUrl);//读取该文件夹
            
            let imgArr = [];
            files.forEach((file) => {
            	//把每个图片都转为base64格式
                let base64 = fs.readFileSync(imgBaseUrl + '/' + file, 'base64');
                imgArr.push(base64);
            })
            return ctx.body = {
                status: 1,
                data: imgArr //将base64图片数组传给前端,到前端的时候再将base64转成图片显示
            }
        } catch (error) {
            console.log(error)
            return ctx.body = {
                status: 0,
            }
        }
    }
}

module.exports = HomeController;
// app/router.js
router.post('/uploadImg', controller.uploadImg.uploadImg);
router.post('/getImg', controller.uploadImg.getImg);

后端的代码以及接口的配置已经完成,接下来是我使用React框架,Antd的upload组件完成上传图片,以读出图片的前端代码。

import React from 'react';
import { useEffect, useState } from 'react';
import { getImg } from "../../../utils/apis/getImg";
import { Upload, message } from 'antd';

//页面代码
function Check() {

    const [imageUrl, setImgSrc] = useState([])

    const getData = async () => {
        const res = await getImg();
        if (res != 0) {
            let imgUrl = [];
            for (let item of res) {
                let imgSrc = "data:image/jpeg;base64," + item;//做base64的转化
                imgUrl.push(imgSrc);
            }
            setImgSrc(imgUrl);
        }
    }

    function beforeUpload(file) {
        const isJpgOrPng = file.type === 'image/jpeg';
        if (!isJpgOrPng) {
            message.error('仅支持jpg文件');
        }
        const isLt2M = file.size / 1024 / 1024 < 4;
        if (!isLt2M) {
            message.error('图片不能大于 4MB!');
        }
        return isJpgOrPng && isLt2M;
    }

    const handleChange = async info => {
        if (info.file.status === 'uploading') {
            return;
        }
        if (info.file.status === 'done') {
            console.log(info.file.response);
            if (info.file.response.status == 1) {
                await getData();
                message.info("上传成功");
            }
        }
    };

    useEffect(async () => {
        await getData();//一打开页面就会去请求后端的图片
    }, [])

    const uploadButton = (
        <div>
            <div style={{ marginTop: 8 }}>Upload</div>
        </div>
    );

    return (
        <div>
            <Upload
                name="avatar"
                listType="picture-card"
                className="avatar-uploader"
                showUploadList={false}
                action="http://127.0.0.1:7002/uploadImg"
                beforeUpload={beforeUpload}
                onChange={handleChange}
            >
                {uploadButton}
            </Upload>
            <div>
                {
                    imageUrl.map((item, index) => {
                        return (<span key={index}>
                            <img src={item} alt="avatar" style={{ width: '35%' }} />
                        </span>)
                    })
                }
            </div>
        </div>
    );
}
export default Check;

封装的axios:

//  src/utils/api.js
import axios from 'axios';
const $api = axios.create({
    baseURL: 'http://127.0.0.1:7002' //我的后端端口设置成7002,egg本身默认是7001,具体的端口根据自己的egg来写
}

二次封装的请求图片函数

// src/utils/apis/getImg.js![在这里插入图片描述](https://img-blog.csdnimg.cn/785d6e3f1e6948689d9f2324ad8aa372.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YWI6L-b546p5oSP,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

import $api from '../api';
export const getImg = async ({ ...params }) => {
    const res = await $api.post('/getImg', params);
    console.log(res.data)
    if (res.data.status == 1)
        return res.data.data;
    else return 0
}

到此为止代码就完成了。点击Upload选择图片上传,完成上传后页面重新向后端获取到图片,刷新页面
在这里插入图片描述
上传的图片被曝存在egg的项目中,如下:
在这里插入图片描述
这样一个单一的上传图片的功能就完成了。另外实际的项目中肯定是需要将图片的路径存入数据库中,此处没有给出,希望参考的小伙伴自己写的时候加上去吧~

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

structrue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值