在做项目过程中,常常会涉及保存图片的功能,以下是我使用egg.js+Antd完成的保存单张图片、从后端将图片传给前端的代码。
egg代码
项目思路:
- 将前端获得的图片存放在egg项目的某个文件夹中
- 将图片的地址存入数据库中
- 读取图片时,将数据库中的图片路径取出,转为base64格式传给前端
- 前端将base64转为图片显示
以下是我省去将图片路径写入数据库的步骤的代码。
在egg的控制器中某个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 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;
}
return ctx.body = {
status: 1,
};
} catch (error) {
console.log(error);
ctx.body = {
status: 0
};
}
}
async getImg() {
const ctx = this.ctx;
try {
let files = fs.readdirSync(imgBaseUrl);
let imgArr = [];
files.forEach((file) => {
let base64 = fs.readFileSync(imgBaseUrl + '/' + file, 'base64');
imgArr.push(base64);
})
return ctx.body = {
status: 1,
data: imgArr
}
} catch (error) {
console.log(error)
return ctx.body = {
status: 0,
}
}
}
}
module.exports = HomeController;
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;
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:
import axios from 'axios';
const $api = axios.create({
baseURL: 'http://127.0.0.1:7002'
}
二次封装的请求图片函数
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的项目中,如下: 这样一个单一的上传图片的功能就完成了。另外实际的项目中肯定是需要将图片的路径存入数据库中,此处没有给出,希望参考的小伙伴自己写的时候加上去吧~
|