Одна статья для понимания загрузки файлов в eggjs

Node.js

1. Базовая конфигурация

существуетeggjsзагрузить файл вофициальная документация

  • 1. Настройте маршрут загрузки

    module.exports = (app) => {
      const { router, controller } = app;
      router.resources('file', '/api/v1/file', controller.file);
    };
    
  • 2. Вconfig/config.default.jsБазовая конфигурация для загрузки в конфигурационный файл (см.официальная документация)

    ...
    // 配置上传
    config.multipart = {
      fileSize: '50mb',
      mode: 'stream',
      fileExtensions: ['.xls', '.txt'], // 扩展几种上传的文件格式
    };
    ...
    
  • 3. Установите несколько основных пакетов

    npm install await-stream-ready stream-wormhole dayjs
    

2. Используйтеformзагрузка формы

  • 1. Код шаблона

    <form method="POST" action="/api/v1/file" enctype="multipart/form-data">
      title: <input name="title" /> file: <input name="file" type="file" />
      <button type="submit">Upload</button>
    </form>
    
  • 2. Использование в контроллереfsи поток данных записывается в файл (на уровне контроллера)
async create() {
  // 获取文件流
  const stream = await this.ctx.getFileStream();
  // 定义文件名
  const filename = Date.now() + path.extname(stream.filename).toLocaleLowerCase();
  // 目标文件
  const target = path.join('app/public/uploads', filename);
  //
  const writeStream = fs.createWriteStream(target);
  console.log('-----------获取表单中其它数据 start--------------');
  console.log(stream.fields);
  console.log('-----------获取表单中其它数据 end--------------');
  try {
    //异步把文件流 写入
    await awaitWriteStream(stream.pipe(writeStream));
  } catch (err) {
    //如果出现错误,关闭管道
    await sendToWormhole(stream);
    // 自定义方法
    this.error(err);
  }
  // 自定义方法
  this.success({ url: '/public/uploads/' + filename });
}
  • 3, может быть сгенерированоurlАдрес уровня службы доставки в базу данных

3. Используйтеajaxзагрузить файлы

  • 1. Базовыйhtmlстраница

    <h1>ajax提交</h1>
    <input type="text" id="username" />
    <input name="file" type="file" id="file" />
    <button id="btn">提交</button>
    
  • 2,jqизajax

    <script>
      $('#btn').on('click', function() {
        console.log('提交按钮');
        let formData = new FormData();
        formData.append('title', $('#username').val());
        formData.append('image', $('#file')[0].files[0]);
        console.log(formData);
        $.ajax({
          url: '/api/v1/file',
          data: formData,
          method: 'post',
          contentType: false,
          processData: false,
          success: function(result) {
            console.log(result);
          },
        });
      });
    </script>
    

В-четвертых, загружаемые файлы классифицируются и архивируются по времени.

  • 1. Измените контроллер для загрузки кода

    const fs = require('fs');
    const path = require('path');
    //故名思意 异步二进制 写入流
    const awaitWriteStream = require('await-stream-ready').write;
    //管道读入一个虫洞。
    const sendToWormhole = require('stream-wormhole');
    const dayjs = require('dayjs');
    
    async create() {
      const stream = await this.ctx.getFileStream();
      console.log('-----------获取数据 start--------------');
      console.log(stream.fields);
      console.log('-----------获取数据 end--------------');
      // 基础的目录
      const uplaodBasePath = 'app/public/uploads';
      // 生成文件名
      const filename = `${Date.now()}${Number.parseInt(
        Math.random() * 1000,
      )}${path.extname(stream.filename).toLocaleLowerCase()}`;
      // 生成文件夹
      const dirname = dayjs(Date.now()).format('YYYY/MM/DD');
      function mkdirsSync(dirname) {
        if (fs.existsSync(dirname)) {
          return true;
        } else {
          if (mkdirsSync(path.dirname(dirname))) {
            fs.mkdirSync(dirname);
            return true;
          }
        }
      }
      mkdirsSync(path.join(uplaodBasePath, dirname));
      // 生成写入路径
      const target = path.join(uplaodBasePath, dirname, filename);
      // 写入流
      const writeStream = fs.createWriteStream(target);
      try {
        //异步把文件流 写入
        await awaitWriteStream(stream.pipe(writeStream));
      } catch (err) {
        //如果出现错误,关闭管道
        await sendToWormhole(stream);
        this.error();
      }
      this.success({ url: path.join('/public/uploads', dirname, filename) });
    }
    
  • 2. Остальные остаются без изменений

  • 3. Загрузите созданный каталог

    2019
    └── 06
        └── 21
            ├── 1561097630832563.png
            └── 1561097675536863.jpeg
    

5. Извлечь его в контроллер базового класса и классифицировать переданные параметры

  • 1. В контроллере базового класса

    const { Controller } = require('egg');
    const fs = require('fs');
    const path = require('path');
    //故名思意 异步二进制 写入流
    const awaitWriteStream = require('await-stream-ready').write;
    //管道读入一个虫洞。
    const sendToWormhole = require('stream-wormhole');
    const dayjs = require('dayjs');
    
    class BaseController extends Controller {
      // 上传文件的通用方法
      async uploadFile(category = '') {
        const stream = await this.ctx.getFileStream();
        // 基础的目录
        const uplaodBasePath = 'app/public/uploads';
        // 生成文件名
        const filename = `${Date.now()}${Number.parseInt(
          Math.random() * 1000,
        )}${path.extname(stream.filename).toLocaleLowerCase()}`;
        // 生成文件夹
        const dirname = dayjs(Date.now()).format('YYYY/MM/DD');
        function mkdirsSync(dirname) {
          if (fs.existsSync(dirname)) {
            return true;
          } else {
            if (mkdirsSync(path.dirname(dirname))) {
              fs.mkdirSync(dirname);
              return true;
            }
          }
        }
        mkdirsSync(path.join(uplaodBasePath, category, dirname));
        // 生成写入路径
        const target = path.join(uplaodBasePath, category, dirname, filename);
        // 写入流
        const writeStream = fs.createWriteStream(target);
        try {
          //异步把文件流 写入
          await awaitWriteStream(stream.pipe(writeStream));
        } catch (err) {
          //如果出现错误,关闭管道
          await sendToWormhole(stream);
          return {
            error: '错误',
          };
        }
        return {
          url: path.join('/public/uploads', category, dirname, filename),
          fields: stream.fields,
        };
      }
    }
    module.exports = BaseController;
    
  • 2. Используйте его в контроллере, который загружает файл

    const Controller = require('./../core/base_controller');
    class FileController extends Controller {
      async create() {
        // 上传头像的,会在uploads文件夹下有个avatar的文件夹下面才是2019、06、21
        const { url, fields } = await this.uploadFile('avatar');
        const result = await 服务层;
        this.success(url);
      }
    }
    
  • 3. Остальные остаются без изменений