Egg.js 实现向服务器上传图片

1.安装时间处理 及 压缩 模块

yarn add silly-datetime pump

2.文件保存路径

config/config.default.js

config.uploadDir = 'app/public/avatar/upload';

3.创建tools service
app/service/tools.js

'use strict';

const Service = require('egg').Service;
const path = require("path");
const sd = require('silly-datetime');
const mkdirp = require('mkdirp');

class ToolsService extends Service {
  /**
   * 获取文件上传目录
   * @param {*} filename
   */
  async getUploadFile(filename) {
    // 1.获取当前日期
    let day = sd.format(new Date(), 'YYYYMMDD');
    // 2.创建图片保存的路径
    let dir = path.join(this.config.uploadDir, day);
    await mkdirp(dir); // 不存在就创建目录
    let date = Date.now(); // 毫秒数
    // 返回图片保存的路径
    let uploadDir = path.join(dir, date + path.extname(filename));
    // app\public\avatar\upload\20200312\1536895331666.png
    return {
      uploadDir,
      saveDir: this.ctx.origin + uploadDir.slice(3).replace(/\\/g, '/')
    }
  }
}

module.exports = ToolsService;

4.调用 controller
app/controller/article.js

// 保存头像/封面
async saveAvatar() {
  const { ctx } = this;
  const parts = ctx.multipart({ autoFields: true });
  let files = {};
  let stream;
  while ((stream = await parts()) != null) {
    if(!stream.filename){
      break;
    }
    const fieldname = stream.fieldname; // file表单的名字
    // 上传图片的目录
    const dir = await this.service.tools.getUploadFile(stream.filename);
    const target = dir.uploadDir;
    const writeStream = fs.createWriteStream(target);

    await pump(stream, writeStream);

    files = Object.assign(files, {
      [fieldname]: dir.saveDir
    });
  }

  if(Object.keys(files).length > 0){
    ctx.body = {
      code: 200,
      message: '图片上传成功',
      data: files
    }
  }else{
    ctx.body = {
      code: 500,
      message: '图片上传失败',
      data: {}
    }
  }
}

5.配置路由

// 上传图片/头像/封面
router.post('/tools/saveavatar', controller.article.saveAvatar);

6.客户端页面逻辑代码
封装组件
src/components/UploadAvatar.js

/**
 * 上传头像/封面
 */
import React from 'react';
import { Upload, Icon, message } from 'antd';
import { BaseUrl } from '../../utils/constants';

function getBase64(img, callback) {
  const reader = new FileReader();
  reader.addEventListener('load', () => callback(reader.result));
  reader.readAsDataURL(img);
}

function beforeUpload(file) {
  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
  if (!isJpgOrPng) {
    message.error('仅支持JPG/PNG文件');
  }
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isLt2M) {
    message.error('图片必须小于2MB!');
  }
  return isJpgOrPng && isLt2M;
}

class Avatar extends React.Component {
  state = {
    loading: false,
  };

  componentDidMount() {
    if(this.props.value) this.setState({ imageUrl: this.props.value});
  }

  handleChange = info => {
    const { name = "avatar"} = this.props;
    if (info.file.status === 'uploading') {
      this.setState({ loading: true });
      return;
    }
    if (info.file.status === 'done') {
      // 获取服务器返回值
      const { response } = info.file;
      if(response.data){
        this.props.onChange && this.props.onChange(response.data[name]);
      }

      getBase64(info.file.originFileObj, imageUrl =>
        this.setState({
          imageUrl,
          loading: false,
        }),
      );
    }
  };

  render() {
    const uploadButton = (
      <div>
        <Icon type={this.state.loading ? 'loading' : 'plus'} />
        <div className="ant-upload-text">上传</div>
      </div>
    );
    const { imageUrl } = this.state;
    const { name = "avatar" } = this.props;
    return (
      <Upload
        name={name}
        listType="picture-card"
        className="avatar-uploader"
        showUploadList={false}
        action={`${BaseUrl}/tools/saveavatar`}
        beforeUpload={beforeUpload}
        onChange={this.handleChange}
      >
        {imageUrl ? <img src={imageUrl} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
      </Upload>
    );
  }
}

export default Avatar;

调用

<Form.Item label="封面">
  {getFieldDecorator('cover', {
    rules: [{ required: true, message: '请上传封面' }],
    initialValue: 'https://img2.mukewang.com/szimg/5d1032ab08719e0906000338.jpg'
  })(<UploadAvatar name={"cover"} />)}
</Form.Item>

.

posted @ 2020-03-18 12:00  每天都要进步一点点  阅读(5384)  评论(2编辑  收藏  举报