Skip to content
导航栏

# 文件上传下载功能

当在 api 中的传入参数中使用了$file.file引用符,yao 框架会把上传的文件保存成临时文件。并返回一个文件数据结构为 UploadFile 的对象。

这个第二个.file 就是在文件上传时的的元数据中的name

通常来说,在浏览器上传时的请求格式是这样的,其中的name="file"就对应上面的$file.file,如果是其它类型的,就使用不同的name进行引用。比如其它的像image,video

txt
------WebKitFormBoundaryyNSuPN4V37SH3V5y
Content-Disposition: form-data; name="file"; filename="baner01.png"
Content-Type: image/png


------WebKitFormBoundaryyNSuPN4V37SH3V5y--

当文件上传到服务器后,文件会先存在在一个服务器的临时目录,比如说 linux 下是/temp目录。并且文件名会是生成的唯一名称。并且返回一个描述文件信息的对象。

json
{
  "name": "文件名",
  "tempFile": "临时文件名",
  "size": "文件大小",
  "mimeType": "文件类型"
}
go
type UploadFile struct {
    Name     string               `json:"name"`
    TempFile string               `json:"tempFile"`
    Size     int64                `json:"size"`
    Header   textproto.MIMEHeader `json:"mimeType"`
}

在 apis 目录定义一个新的文件上传下载接口:

json
{
  "name": "存储接口",
  "version": "1.0.0",
  "description": "存储接口API",
  "group": "storage",
  "guard": "bearer-jwt",
  "paths": [
    {
      "path": "/upload",
      "method": "POST",
      "process": "fs.system.Upload",
      "in": ["$file.file"],
      "out": {
        "status": 200,
        "type": "application/json"
      }
    },
    {
      "path": "/download",
      "method": "GET",
      "guard": "-",
      "process": "fs.system.Download",
      "in": ["$query.name"],
      "out": {
        "status": 200,
        "body": "{{content}}",
        "headers": { "Content-Type": "{{type}}" }
      }
    }
  ]
}

文件处理器

yao 内置了几个与文件上传下载相关的处理器:

  • fs.system.Upload,把文件从临时目录写入到应用目录下,并以当天的目录创建一个子目录,并返回文件名,这个文件名也是一个自动生成的唯一的文件名。

  • fs.system.Download,读取应用目录下的文件,并通过 http 接口返回。文件的 mime 信息会自动根据文件进行判断。这个接口会返回以下的消息,需要注意的是 mimetype 并不是上传的类型,因为并没有保存到数据库中,只是根据文件本身的信息头作判断,有可能会有误差。

    json
    {
      "content": "文件内容",
      "type": "mime-type"
    }
    

另外也可以使用 js 函数自定义文件上传功能。

js
//scripts.file.upload
function upload(file) {
  // "map[mimeType:map[Content-Disposition:[form-data; name=\"file\"; filename=\"blob\"]
  // Content-Type:[image/png]] name:blob size:108505
  // tempFile:C:\\Users\\USER\\AppData\\Local\\Temp\\upload2241272960\\file-2567307823]"

  // 这里不能直接使用处理器fs.system.Upload,因为经过js桥接后,数据结构已经变化。
  // https://github.com/wwsheng009/gou/commit/7fafef2100057343024e6fbe7728fd7d58cb28c9

  // 读取临时文件
  const f = Process('fs.system.ReadFile', file.tempFile);

  const ts = Process('utils.now.Timestampms');
  // 自定义文件路径
  const fn = `/data/${ts}`;
  // 写入文件
  Process('fs.system.WriteFile', fn, f, '0644');
  // 返回文件下载地址,这个地址也可以自定义,需要配合api中的下载地址定义
  return `/yao-api/download?name=${fn}`;
}

下载地址:

sh
http://dev.com:5099/yao-api/download?name=test.png

文件下载测试页面。

html
<!DOCTYPE html>
<html>
  <head>
    <title>Download PNG File Example</title>
  </head>
  <body>
    <h1>Download PNG File Example</h1>
    <p>Click the link below to download a PNG file in a new window:</p>
    <a
      href="http://dev.com:5099/yao-api/download?name=test.png"
      download
      target="_blank"
      >Download PNG File</a
    >
  </body>
</html>