Skip to content
导航栏

文件上传

可以使用 fs.* 处理器, 制作文件上传接口。在管理界面中, 使用 Upload 组件实现文件、图片或视频上传功能。

约定

  1. 示例中约定应用根目录为 /data/app, 实际编写时需替换为应用根目录。
  2. 示例中约定服务器地址为 http://127.0.0.1:5099, 实际编写时需自行替换。
  3. 使用 <> 标识自行替换的内容。 例如: icon-<图标名称>, 实际编写时应替换为: icon-foo, icon-bar ...

文件上传

product Model 添加一个 images JSON 字段用来保存产品图片文件地址。

json
{
  "name": "产品",
  "table": { "name": "product", "comment": "产品表" },
  "columns": [
    { "label": "ID", "name": "id", "type": "ID", "comment": "ID" },
    { "label": "日期", "name": "day", "type": "datetime", "index": true },
    {
      "label": "名称",
      "name": "name",
      "type": "string",
      "length": 128,
      "index": true
    },
    {
      "label": "图集",
      "name": "images",
      "type": "json",
      "nullable": true
    },
    {
      "label": "上架状态",
      "name": "online",
      "type": "boolean",
      "default": false,
      "comment": "上架状态 true 上架 false 下架",
      "index": true
    },
    {
      "label": "状态",
      "name": "status",
      "type": "enum",
      "default": "enabled",
      "option": ["enabled", "disabled"],
      "comment": "状态:enabled打开,disabled关闭",
      "index": true
    },
    { "label": "用户ID", "name": "user_id", "type": "integer", "index": true },
    { "label": "总金额", "name": "amount", "type": "decimal", "index": true },
    { "label": "备注", "name": "remark", "type": "text", "nullable": true }
  ],
  "values": [],
  "relations": {
    "users": {
      "type": "hasOne",
      "model": "xiang.user",
      "key": "id",
      "foreign": "user_id",
      "query": {}
    }
  },
  "option": { "timestamps": true, "soft_deletes": true }
}

更新数据表结构

bash
yao migrate -n product

Upload & Image 组件

product Table 添加图集字段, 实现图片上传管理。

使用 Cloud Props 生成一个文件上传接口。

jsonc
{
  "图集": {
    "bind": "images",
    "view": { "type": "Image", "compute": "Downalod" }, // 使用 Image 组件显示已上传图片
    "edit": {
      "type": "Upload",
      "compute": "Upload",
      "props": {
        "filetype": "image", // 上传文件类型设定为 image
        "$api": {
          "process": "fs.system.Upload" // 声明一个API接口, 并绑定 fs.system.Upload 处理器
        }
      }
    }
  }
}

使用 DownalodUpload Compute 处理器转换图片预览 URL

Compute原始值转换后
Downalod["/path/img.png"]["/api/__yao/table/<Widget ID>/download/<field>?name=/path/img.png"]
Upload["/api/__yao/table/<Widget ID>/download/<field>?name=/path/img.png"]["/path/img.png"]

组件 Props 以 $ 开头的 KEY, 引擎将其解析为一个 API 接口。并把接口路由和查询参数, 作为参数替换原值。

json
{
  "name": "产品",
  "action": { "bind": { "model": "product" } },
  "layout": {
    "header": { "preset": {} },
    "filter": {
      "columns": [{ "name": "名称", "width": 4 }],
      "actions": [
        {
          "title": "添加产品",
          "icon": "icon-plus",
          "width": 3,
          "action": {
            "Common.openModal": {
              "Form": { "type": "edit", "model": "product" }
            }
          }
        }
      ]
    },
    "table": {
      "columns": [
        { "name": "图集", "width": 300 },
        { "name": "联动", "width": 200 },
        { "name": "名称", "width": 200 },
        { "name": "备注", "width": 200 },
        { "name": "上架状态", "width": 200 }
      ],
      "operation": {
        "fold": false,
        "width": 255,
        "actions": [
          {
            "title": "查看",
            "icon": "icon-eye",
            "action": {
              "Common.openModal": {
                "Form": { "type": "view", "model": "product" }
              }
            }
          },
          {
            "title": "编辑",
            "icon": "icon-edit-2",
            "action": {
              "Common.openModal": {
                "Form": { "type": "edit", "model": "product" }
              }
            }
          }
        ]
      }
    }
  },
  "fields": {
    "table": {
      "图集": {
        "bind": "images",
        "view": { "type": "Image", "compute": "Download" },
        "edit": {
          "type": "Upload",
          "compute": "Upload",
          "props": {
            "filetype": "image",
            "$api": { "process": "fs.system.Upload" }
          }
        }
      },
      "联动": {
        "bind": "online",
        "view": {
          "bind": "new_field",
          "type": "Text",
          "compute": {
            "process": "Concat",
            "args": ["$C(row.name)", "(", "$C(row.remark)", ")"]
          }
        },
        "edit": {
          "type": "Select",
          "props": {
            "options": [
              { "label": "已上架", "value": true },
              { "label": "已下架", "value": false }
            ]
          }
        }
      }
    }
  }
}

自定义上传接口

使用 API Widget 创建一个文件上传接口, 将处理器指定为 fs.system.Upload。

/data/app/apis/upload.http.json

jsonc
{
  "name": "文件上传",
  "version": "1.0.0",
  "description": "文件上传",
  "guard": "bearer-jwt",
  "paths": [
    {
      "path": "/file",
      "method": "POST",
      "guard": "-",
      "process": "fs.system.Upload",
      "in": ["$file.file"],
      "out": { "status": 200, "type": "application/json" }
    }
  ]
}

运行调试

添加一个测试文件用于上传

bash
mkdir -p /data/app/data/ # 如 data 目录不存在, 创建一个 data 目录
echo "Upload Test" > /data/app/data/upload-test.txt
bash
curl http://127.0.0.1:5099/api/upload/file \
  -F file=@data/upload-test.txt

自定义上传逻辑

逻辑编排

使用 Flow

新建一个 Flow DSL 文件编排上传逻辑

jsonc
{
  "label": "文件上传",
  "version": "1.0.0",
  "description": "文件上传",
  "nodes": [
    {
      "name": "文件",
      "process": "fs.system.ReadFile",
      "args": ["{{$in[0].tempFile}}"]
    },
    {
      "name": "当前时刻",
      "process": "utils.now.Timestampms",
      "args": []
    },
    {
      "name": "名称",
      "process": "utils.str.Concat",
      "args": ["{{$res.当前时刻}}", ".txt"]
    },
    {
      "name": "文件名",
      "process": "utils.str.JoinPath",
      "args": ["/", "texts", "{{$res.名称}}"]
    },
    {
      "name": "保存文件",
      "process": "fs.system.WriteFile",
      "args": ["{{$res.文件名}}", "{{$res.文件}}", "0644"]
    }
  ],
  "output": "{{$res.文件名}}"
}

运行调试

创建个临时文件用于上传

bash
tempfile=$(mktemp)
echo "Upload Test" > $tempfile
echo $tempfile
bash
yao run flows.upload.file '::{"tempFile":"<tempfile>"}'

使用 Script

新建一个 Script 脚本编排上传逻辑

javascript
/**
 * 上传文件
 * @param {*} temp
 * @returns
 */
function File(temp) {
  temp = temp || {};
  if (!temp.tempFile) {
    throw new Exception('参数错误', 400);
  }

  var fs = new FS('system');
  let tempFile = temp.tempFile || null;
  var data = fs.ReadFile(tempFile);
  let now = new Date().getTime();
  let file = `/texts/${now}.txt`;
  fs.WriteFile(file, data, 0644);
  return file;
}

运行调试

创建个临时文件用于上传

bash
tempfile=$(mktemp)
echo "Upload Test" > $tempfile
echo $tempfile
bash
yao run scripts.upload.File '::{"tempFile":"<tempfile>"}'

在接口中使用

/data/app/apis/upload.http.json

jsonc
{
  "name": "文件上传",
  "version": "1.0.0",
  "description": "文件上传",
  "guard": "bearer-jwt",
  "group": "upload",
  "paths": [
    {
      "path": "/file",
      "method": "POST",
      "guard": "-",
      "process": "fs.system.Upload",
      "in": ["$file.file"],
      "out": { "status": 200, "type": "application/json" }
    },
    {
      "path": "/flow",
      "method": "POST",
      "guard": "-",
      "process": "flows.upload.file",
      "in": ["$file.file"],
      "out": { "status": 200, "type": "application/json" }
    },
    {
      "path": "/script",
      "method": "POST",
      "guard": "-",
      "process": "scripts.upload.File",
      "in": ["$file.file"],
      "out": { "status": 200, "type": "application/json" }
    }
  ]
}

运行调试

添加一个测试文件用于上传

bash
mkdir -p /data/app/data/ # 如 data 目录不存在, 创建一个 data 目录
echo "Upload Test" > /data/app/data/upload-test.txt
bash
curl http://127.0.0.1:5099/api/upload/file \
  -F file=@data/upload-test.txt
bash
curl http://127.0.0.1:5099/api/upload/flow \
  -F file=@data/upload-test.txt
bash
curl http://127.0.0.1:5099/api/upload/script \
  -F file=@data/upload-test.txt

在 Upload 组件中使用

使用 Cloud Props

jsonc
{
  "图集": {
    "bind": "images",
    "view": { "type": "Image", "compute": "Download" },
    "edit": {
      "type": "Upload",
      "compute": "Upload",
      "props": {
        "filetype": "image",
        "$api": {
          "process": "flows.upload.file" // 绑定 flows.upload.file 处理器
        }
      }
    }
  }
}
jsonc
{
  "图集": {
    "bind": "images",
    "view": { "type": "Image", "compute": "Download" },
    "edit": {
      "type": "Upload",
      "compute": "Upload",
      "props": {
        "filetype": "image",
        "$api": {
          "process": "scripts.upload.File" // 绑定 scripts.upload.File 处理器
        }
      }
    }
  }
}

使用 props.api

jsonc
{
  "图集": {
    "bind": "images",
    "view": { "type": "Image", "compute": "Download" },
    "edit": {
      "type": "Upload",
      "compute": "Upload",
      "props": { "filetype": "image", "api": "/apis/upload/flow" }
    }
  }
}
jsonc
{
  "图集": {
    "bind": "images",
    "view": { "type": "Image", "compute": "Download" },
    "edit": {
      "type": "Upload",
      "compute": "Download",
      "props": { "filetype": "image", "api": "/apis/upload/script" }
    }
  }
}