上传
将文件上传到 API,并保存到文件夹或数据库中。
简介
当我们需要将文件发送到 REST API 服务时,在 Netuno 中有多种方式可以实现这种开发。
通常,文件会放在 HTTP 请求体中,并以 multipart 格式组织,这是前端最常见的做法,例如当我们填写表单并且其中有一个用于选择文件的字段时。
另一种方式是,当我们希望 REST API 完全使用 JSON 时,可以将文件字节以 Base64 编码作为 JSON 对象中的值发送。
文件
通过 _req.file 可以传入字段名,从而获取已上传文件的对象,如下所示:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 我的文件 = _req.file("文件");
const 我的文件 = _req.file("文件");
我的文件 = _req.file("文件")
我的文件 = _req.file("文件")
val 我的文件 = _req.file("文件")
final 我的文件 = _req.file("文件")
也就是说,_req 包含我们在 HTTP 请求体中接收到的所有数据。
通过 file 方法可以获取表示已上传文件的对象。
如果没有任何文件,获取到的值可能为 null。
图片
当我们接收图片时,通常需要调整其尺寸,以保证一致性并减少图片占用的空间。
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 我的文件 = _req.getFile("图片");
if (我的文件 != null
&& (我的文件.isExtension("jpeg")
|| 我的文件.isExtension("jpg")
|| 我的文件.isExtension("png")
)) {
const 我的图片 = _image.init(我的文件)
.resize(200, 200)
.file(我的文件.baseName() +".jpg", "jpeg");
_header.contentTypeJPG();
_out.copy(我的图片);
}
const 我的文件 = _req.getFile("图片");
if (我的文件 != null
&& (我的文件.isExtension("jpeg")
|| 我的文件.isExtension("jpg")
|| 我的文件.isExtension("png")
)) {
const 我的图片 = _image.init(我的文件)
.resize(200, 200)
.file(我的文件.baseName() +".jpg", "jpeg");
_header.contentTypeJPG();
_out.copy(我的图片);
}
我的文件 = _req.getFile("图片")
if 我的文件 is not None and (
我的文件.isExtension("jpeg")
or 我的文件.isExtension("jpg")
or 我的文件.isExtension("png")):
我的图片 = (
_image.init(我的文件)
.resize(200, 200)
.file(我的文件.baseName() +".jpg", "jpeg")
)
_header.contentTypeJPG()
_out.copy(我的图片)
我的_文件 = _req.getFile("图片")
if !我的_文件.nil? && (
我的_文件.isExtension("jpeg") ||
我的_文件.isExtension("jpg") ||
我的_文件.isExtension("png")
)
我的_图片 = _image.init(我的_文件)
.resize(200, 200)
.file(我的_文件.baseName() +".jpg", "jpeg")
_header.contentTypeJPG()
_out.copy(我的_图片)
end
val 我的文件 = _req.getFile("图片")
if (我的文件 != null
&& (我的文件.isExtension("jpeg")
|| 我的文件.isExtension("jpg")
|| 我的文件.isExtension("png")
)) {
val 我的图片 = _image.init(我的文件.input())
.resize(200, 200)
.file(我的文件.baseName() +".jpg", "jpeg")
_header.contentTypeJPG()
_out.copy(我的图片.input())
}
final 我的文件 = _req.getFile("图片")
if (我的文件 != null
&& (我的文件.isExtension("jpeg")
|| 我的文件.isExtension("jpg")
|| 我的文件.isExtension("png")
)) {
final 我的图片 = _image.init(我的文件)
.resize(200, 200)
.file(我的文件.baseName() +".jpg", "jpeg")
_header.contentTypeJPG()
_out.copy(我的图片)
}
借助多语言低代码编程资源 Image,我们可以操作图片,进行裁剪、调整尺寸、创建新图片等。
如何在 JSON 中使用 Base64
要在发送给服务的 JSON 中上传文件,我们可以定义一个属性,其值为:
data:image/png;base64,...
其中 ... 后跟以 Base64 编码的文件字节序列。
文件类型跟在 data 后面,例如:
- PNG:
image/png。 - JPG:
image/jpeg - TXT:
text/plain - PDF:
application/pdf - XLSX:
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
请参见以下示例:将一个小的 PNG 图片文件在 JSON 中发送到服务:
{
"文件": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAFIGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgZXhpZjpDb2xvclNwYWNlPSIxIgogICBleGlmOlBpeGVsWERpbWVuc2lvbj0iMyIKICAgZXhpZjpQaXhlbFlEaW1lbnNpb249IjMiCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMyIKICAgdGlmZjpJbWFnZVdpZHRoPSIzIgogICB0aWZmOlJlc29sdXRpb25Vbml0PSIyIgogICB0aWZmOlhSZXNvbHV0aW9uPSI3Mi8xIgogICB0aWZmOllSZXNvbHV0aW9uPSI3Mi8xIgogICB4bXA6TWV0YWRhdGFEYXRlPSIyMDI1LTEyLTI5VDE5OjEyOjI3WiIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjUtMTItMjlUMTk6MTI6MjdaIj4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0icHJvZHVjZWQiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFmZmluaXR5IERlc2lnbmVyIDEuMTAuNSIKICAgICAgeG1wTU06d2hlbj0iMjAyNS0wMi0yM1QyMjoxNDozM1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0icHJvZHVjZWQiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFmZmluaXR5IDMuMC4xIgogICAgICBzdEV2dDp3aGVuPSIyMDI1LTEyLTI5VDE5OjEyOjI3WiIvPgogICAgPC9yZGY6U2VxPgogICA8L3htcE1NOkhpc3Rvcnk+CiAgPC9yZGY6RGVzY3JpcHRpb24+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+UGhcxwAAAYFpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAACiRdZG7SwNBEIe/JEqCRhS0sFAIEq3iG4I2ggmigkiIEXw1yZmHkMdxlyDBVrANKIg2vgr9C7QVrAVBUQSx1lbRRuWc84QEMbPMzre/3Rl2Z8EeSSsZvaYPMtm8Fh4PeObmFzzOZ9y004yL3qiiq6Oh0BRV7f0Wmxmvu81a1c/9a/XLcV0Bm0t4RFG1vPCE8NRqXjV5S7hFSUWXhU+EfZpcUPjG1GMWP5mctPjTZC0SDoK9SdiTrOBYBSspLSMsL8ebSReU3/uYL3HHs7MzEjvE29AJM04AD5OMEcRPP8My++lmgB5ZUSW/7yd/mpzkKjKrFNFYIUmKPD5RC1I9LjEhelxGmqLZ/7991RODA1Z1dwBqHw3jtROcm/BVMoyPA8P4OgTHA5xny/m5fRh6E71U1rx70LgOpxdlLbYNZxvQeq9GteiP5BC3JxLwcgwN89B8BXWLVs9+9zm6g8iafNUl7OxCl5xvXPoGe8Rn71E5kqUAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAySURBVAiZAScA2P8BJYrEogr//l3h5+qlBP4HCF3n/AAA/wP7WwLu7PKk+eHWAPzWyKSmfRbbIj23ZQAAAABJRU5ErkJggg=="
}
我们可以按以下方式获取上传的文件:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 我的文件 = _req.getFile("文件");
if (我的文件 != null) {
_out.json(
_val.map()
.set("结果", true)
.set("名称", 我的文件.name())
.set("大小字节", 我的文件.size())
.set("大小KB", 我的文件.sizeKB())
.set("大小MB", 我的文件.sizeMB())
.set("大小GB", 我的文件.sizeGB())
);
} else {
_out.json(
_val.map()
.set("结果", false)
);
}
const 我的文件 = _req.getFile("文件");
if (我的文件 != null) {
_out.json(
_val.map()
.set("结果", true)
.set("名称", 我的文件.name())
.set("大小字节", 我的文件.size())
.set("大小KB", 我的文件.sizeKB())
.set("大小MB", 我的文件.sizeMB())
.set("大小GB", 我的文件.sizeGB())
);
} else {
_out.json(
_val.map()
.set("结果", false)
);
}
我的文件 = _req.getFile("文件")
if 我的文件 is not None:
_out.json(
_val.map()
.set("结果", True)
.set("名称", 我的文件.name())
.set("大小字节", 我的文件.size())
.set("大小KB", 我的文件.sizeKB())
.set("大小MB", 我的文件.sizeMB())
.set("大小GB", 我的文件.sizeGB())
)
else:
_out.json(
_val.map()
.set("结果", False)
)
我的_文件 = _req.getFile("文件")
if 我的_文件.nil?
_out.json(
_val.map()
.set("结果", true)
.set("名称", 我的_文件.name())
.set("大小字节", 我的_文件.size())
.set("大小KB", 我的_文件.sizeKB())
.set("大小MB", 我的_文件.sizeMB())
.set("大小GB", 我的_文件.sizeGB())
)
else
_out.json(
_val.map()
.set("结果", false)
)
end
val 我的文件 = _req.getFile("文件")
if (我的文件 != null) {
_out.json(
_val.map()
.set("结果", true)
.set("名称", 我的文件.name())
.set("大小字节", 我的文件.size())
.set("大小KB", 我的文件.sizeKB())
.set("大小MB", 我的文件.sizeMB())
.set("大小GB", 我的文件.sizeGB())
)
} else {
_out.json(
_val.map()
.set("结果", false)
)
}
final 我的文件 = _req.getFile("文件")
if (我的文件 != null) {
_out.json(
_val.map()
.set("结果", true)
.set("名称", 我的文件.name())
.set("大小字节", 我的文件.size())
.set("大小KB", 我的文件.sizeKB())
.set("大小MB", 我的文件.sizeMB())
.set("大小GB", 我的文件.sizeGB())
)
} else {
_out.json(
_val.map()
.set("结果", false)
)
}
以上服务生成的输出示例:
{
"名称": "文件.png",
"结果": true,
"大小": 1849,
"大小KB": 1
}
对象
如果文件位于 JSON 内部子对象结构中:
{
"人员": {
"文件": "data:image/png;base64,..."
}
}
可以按以下方式获取:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 我的文件 = _req.getValues("人员").getFile("头像");
const 我的文件 = _req.getValues("人员").getFile("头像");
我的文件 = _req.getValues("人员").getFile("头像")
我的文件 = _req.getValues("人员").getFile("头像")
val 我的文件 = _req.getValues("人员").getFile("头像")
final 我的文件 = _req.getValues("人员").getFile("头像")
数组
如果文件位于 JSON 内部数组结构中:
{
"文件列表": [
"data:image/png;base64,..."
]
}
可以按以下方式获取:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 我的文件 = _req.getValues("文件列表").getFile(0);
const 我的文件 = _req.getValues("文件列表").getFile(0);
我的文件 = _req.getValues("文件列表").getFile(0)
我的文件 = _req.getValues("文件列表").getFile(0)
val 我的文件 = _req.getValues("文件列表").getFile(0)
final 我的文件 = _req.getValues("文件列表").getFile(0)
OpenAPI
Netuno 支持与 OpenAPI 集成,并使用 OpenAPI 定义来验证 HTTP 请求。
关于 Netuno 中的 OpenAPI 的更多内容。
使用 file 类型时,Netuno 会验证该值是否以 JSON 中的文件格式开头,例如:
data:image/png;base64,...
要验证是否在 JSON 对象的某个属性中接收文件:
{
"summary": "文件上传",
"description": "在 JSON 对象中接收文件的服务。",
"type": "object",
"properties": {
"文件": {
"type": "file"
}
},
"required": [
"文件"
]
}
要验证是否在 JSON 数组中接收文件列表:
{
"summary": "多文件上传",
"description": "在 JSON 数组中接收文件列表的服务。",
"properties": {
"文件列表": {
"type": "array",
"items": {
"type": "file"
}
}
},
"required": [
"文件列表"
]
}
保存文件
通常,当服务接收到文件时,我们需要将其保存,例如:
- 数据库:与记录关联的文件,例如用户的文件。
- Storage:应用内部用于管理通用文件的文件夹。
- 文件夹:将文件放到系统中的任意文件夹。
数据库
在表单字段管理中,Netuno 支持 image 和 file 类型,即:
- Image:通用图片文件,JPG 和 PNG。
- File:任意类型的文件。
假设“产品”表单中有一个“图片”字段,我们可以按以下方式保存通过上传发送的文件:
使用 DB Form 的示例:
注意 _db.form 的使用:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 产品Uid = _req.getString("uid");
const 产品图片 = _req.getFile("图片");
if (产品图片 == null) {
_header.status(400);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
);
_exec.stop();
}
const 数据库结果 = _db.form("产品")
.set("图片", 产品图片)
.where(_db.where("uid").equals(产品Uid))
.update();
if (数据库结果.getInt("产品") == 1) {
_out.json(
_val.map()
.set("结果", true)
);
} else {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
);
}
const 产品Uid = _req.getString("uid");
const 产品图片 = _req.getFile("图片");
if (产品图片 == null) {
_header.status(400);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
);
_exec.stop();
}
const 数据库结果 = _db.form("产品")
.set("图片", 产品图片)
.where(_db.where("uid").equals(产品Uid))
.update();
if (数据库结果.getInt("产品") == 1) {
_out.json(
_val.map()
.set("结果", true)
);
} else {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
);
}
产品Uid = _req.getString("uid")
产品图片 = _req.getFile("图片")
if 产品图片 is None:
_header.status(400)
_out.json(
_val.map()
.set("结果", False)
.set("错误", "图片必填")
)
_exec.stop()
数据库结果 = (
_db.form("产品")
.set("图片", 产品图片)
.where(_db.where("uid").equals(产品Uid))
.update()
)
if 数据库结果.getInt("产品") == 1:
_out.json(
_val.map()
.set("结果", True)
)
else:
_header.status(404)
_out.json(
_val.map()
.set("结果", False)
.set("错误", "uid-产品不存在")
)
产品_uid = _req.getString("uid")
产品_图片 = _req.getFile("图片")
if 产品_图片.nil?
_header.status = 400
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
)
_exec.stop
end
数据库_结果 = _db.form("产品")
.set("图片", 产品_图片)
.where(_db.where("uid").equals(产品_uid))
.update()
if 数据库_结果.getInt("产品") == 1
_out.json(
_val.map()
.set("结果", true)
)
else
_header.status = 404
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
)
end
val 产品Uid = _req.getString("uid")
val 产品图片 = _req.getFile("图片")
if (产品图片 == null) {
_header.status(400)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
)
_exec.stop()
}
val 数据库结果 = _db.form("产品")
.set("图片", 产品图片)
.where(_db.where("uid").equals(产品Uid))
.update()
if (数据库结果.getInt("产品") == 1) {
_out.json(
_val.map()
.set("结果", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
)
}
final 产品Uid = _req.getString("uid")
final 产品图片 = _req.getFile("图片")
if (产品图片 == null) {
_header.status(400)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
)
_exec.stop()
}
final 数据库结果 = _db.form("产品")
.set("图片", 产品图片)
.where(_db.where("uid").equals(产品Uid))
.update()
if (数据库结果.getInt("产品") == 1) {
_out.json(
_val.map()
.set("结果", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
)
}
使用经典 update 的示例:
注意 _db.update 的使用:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 产品Uid = _req.getString("uid");
const 产品图片 = _req.getFile("图片");
if (产品图片 == null) {
_header.status(400);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
);
_exec.stop();
}
const 数据库结果 = _db.update(
"产品",
产品Uid,
_val.map()
.set("图片", 产品图片)
);
if (数据库结果 == 1) {
_out.json(
_val.map()
.set("结果", true)
);
} else {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
);
}
const 产品Uid = _req.getString("uid");
const 产品图片 = _req.getFile("图片");
if (产品图片 == null) {
_header.status(400);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
);
_exec.stop();
}
const 数据库结果 = _db.update(
"产品",
产品Uid,
_val.map()
.set("图片", 产品图片)
);
if (数据库结果 == 1) {
_out.json(
_val.map()
.set("结果", true)
);
} else {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
);
}
产品Uid = _req.getString("uid")
产品图片 = _req.getFile("图片")
if 产品图片 is None:
_header.status(400)
_out.json(
_val.map()
.set("结果", False)
.set("错误", "图片必填")
)
_exec.stop()
数据库结果 = (
_db.update(
"产品",
产品Uid,
_val.map()
.set("图片", 产品图片)
)
)
if 数据库结果 == 1:
_out.json(
_val.map()
.set("结果", True)
)
else:
_header.status(404)
_out.json(
_val.map()
.set("结果", False)
.set("错误", "uid-产品不存在")
)
产品_uid = _req.getString("uid")
产品_图片 = _req.getFile("图片")
if 产品_图片.nil?
_header.status = 400
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
)
_exec.stop
end
数据库_结果 = _db.update(
"产品",
产品_uid,
_val.map()
.set("图片", 产品_图片)
)
if 数据库_结果 == 1
_out.json(
_val.map()
.set("结果", true)
)
else
_header.status = 404
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
)
end
val 产品Uid = _req.getString("uid")
val 产品图片 = _req.getFile("图片")
if (产品图片 == null) {
_header.status(400)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
)
_exec.stop()
}
val 数据库结果 = _db.update(
"产品",
产品Uid,
_val.map()
.set("图片", 产品图片)
)
if (数据库结果 == 1) {
_out.json(
_val.map()
.set("结果", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
)
}
final 产品Uid = _req.getString("uid")
final 产品图片 = _req.getFile("图片")
if (产品图片 == null) {
_header.status(400)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "图片必填")
)
_exec.stop()
}
final 数据库结果 = _db.update(
"产品",
产品Uid,
_val.map()
.set("图片", 产品图片)
)
if (数据库结果 == 1) {
_out.json(
_val.map()
.set("结果", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "uid-产品不存在")
)
}
从数据库下载文件
要呈现已存储的文件,我们应创建一个提供文件字节的服务。
对于保存到数据库中的文件(如上述示例),文件本身会放入应用的 Storage 中,而数据库中只存储文件的最终名称。
应用的 Storage 是一个用于存储和组织通用文件结构的文件夹。
因此,在上面的示例中,表单 产品 和字段 图片 的数据库文件存储在:
storage/database/产品/图片/*
Netuno 会自动管理存储文件的名称,以避免文件名重复。
要获取文件,可以创建一个展示产品图片文件的服务,例如:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 产品Uid = _req.getString("uid");
// DB Form:
const 数据库产品 = _db.form("产品")
.where(_db.where("uid").equals(产品Uid))
.first();
// 使用经典 DB 的替代方式:
// const 数据库产品 = _db.get("产品", 产品Uid)
if (数据库产品 == null) {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "产品未找到")
);
_exec.stop();
}
const 数据库产品图片名称 = 数据库产品.getString("图片");
const 存储产品图片文件 = _storage.database(
"产品",
"图片",
数据库产品图片名称
);
if (存储产品图片文件.extension() == "jpg" || 存储产品图片文件.extension() == "jpeg") {
_header.contentTypeJPG();
} else {
_header.contentTypePNG();
}
_header.noCache();
_out.copy(存储产品图片文件.inputStream());
const 产品Uid = _req.getString("uid");
// DB Form:
const 数据库产品 = _db.form("产品")
.where(_db.where("uid").equals(产品Uid))
.first();
// 使用经典 DB 的替代方式:
// const 数据库产品 = _db.get("产品", 产品Uid)
if (数据库产品 == null) {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "产品未找到")
);
_exec.stop();
}
const 数据库产品图片名称 = 数据库产品.getString("图片");
const 存储产品图片文件 = _storage.database(
"产品",
"图片",
数据库产品图片名称
);
if (存储产品图片文件.extension() == "jpg" || 存储产品图片文件.extension() == "jpeg") {
_header.contentTypeJPG();
} else {
_header.contentTypePNG();
}
_header.noCache();
_out.copy(存储产品图片文件.inputStream());
产品Uid = _req.getString("uid")
# DB Form:
数据库产品 = (
_db.form("产品")
.where(_db.where("uid").equals(产品Uid))
.first()
)
# 使用经典 DB 的替代方式:
# 数据库产品 = _db.get("产品", 产品Uid)
if 数据库产品 is None:
_header.status(404)
_out.json(
_val.map()
.set("结果", False)
.set("错误", "产品未找到")
)
_exec.stop()
数据库产品图片名称 = 数据库产品.getString("图片")
存储产品图片文件 = _storage.database(
"产品",
"图片",
数据库产品图片名称
)
if 存储产品图片文件.extension() == "jpg" or 存储产品图片文件.extension() == "jpeg":
_header.contentTypeJPG()
else:
_header.contentTypePNG()
_header.noCache()
_out.copy(存储产品图片文件.inputStream())
产品Uid = _req.getString("uid")
# DB Form:
数据库产品 = _db.form("产品")
.where(_db.where("uid").equals(产品Uid))
.first()
# 使用经典 DB 的替代方式:
# 数据库产品 = _db.get("产品", 产品Uid)
if 数据库产品.nil?
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "产品未找到")
)
_exec.stop()
end
数据库产品图片名称 = 数据库产品.getString("图片")
存储产品图片文件 = _storage.database(
"产品",
"图片",
数据库产品图片名称
)
if 存储产品图片文件.extension() == "jpg" || 存储产品图片文件.extension() == "jpeg"
_header.contentTypeJPG()
else
_header.contentTypePNG()
end
_header.noCache()
_out.copy(存储产品图片文件.inputStream())
val 产品Uid = _req.getString("uid")
// DB Form:
val 数据库产品 = _db.form("产品")
.where(_db.where("uid").equals(产品Uid))
.first()
// 使用经典 DB 的替代方式:
// val 数据库产品 = _db.get("产品", 产品Uid)
if (数据库产品 == null) {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "产品未找到")
)
_exec.stop()
}
val 数据库产品图片名称 = 数据库产品.getString("图片")
val 存储产品图片文件 = _storage.database(
"产品",
"图片",
数据库产品图片名称
)
if (存储产品图片文件.extension() == "jpg" || 存储产品图片文件.extension() == "jpeg") {
_header.contentTypeJPG()
} else {
_header.contentTypePNG()
}
_header.noCache()
_out.copy(存储产品图片文件.inputStream())
final 产品Uid = _req.getString("uid")
// DB Form:
final 数据库产品 = _db.form("产品")
.where(_db.where("uid").equals(产品Uid))
.first()
// 使用经典 DB 的替代方式:
// final 数据库产品 = _db.get("产品", 产品Uid)
if (数据库产品 == null) {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "产品未找到")
)
_exec.stop()
}
final 数据库产品图片名称 = 数据库产品.getString("图片")
final 存储产品图片文件 = _storage.database(
"产品",
"图片",
数据库产品图片名称
)
if (存储产品图片文件.extension() == "jpg" || 存储产品图片文件.extension() == "jpeg") {
_header.contentTypeJPG()
} else {
_header.contentTypePNG()
}
_header.noCache()
_out.copy(存储产品图片文件.inputStream())
注意,_storage 资源(Storage)用于获取文件:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
_storage.database(
"产品", // 表单/表名称。
"图片", // 字段/列名称。
数据库产品图片名称 // 文件名。
);
_storage.database(
"产品", // 表单/表名称。
"图片", // 字段/列名称。
数据库产品图片名称 // 文件名。
);
_storage.database(
"产品", # 表单/表名称。
"图片", # 字段/列名称。
数据库产品图片名称 # 文件名。
)
_storage.database(
"产品", # 表单/表名称。
"图片", # 字段/列名称。
数据库产品图片名称 # 文件名。
)
_storage.database(
"产品", // 表单/表名称。
"图片", // 字段/列名称。
数据库产品图片名称 // 文件名。
)
_storage.database(
"产品", // 表单/表名称。
"图片", // 字段/列名称。
数据库产品图片名称 // 文件名。
)
数据库中只存储文件名,而通过 _storage.database 我们可以获取文件本身。
Storage
我们可以将文件直接保存到应用的 storage 中。
为了避免与数据库文件混在一起,我们应使用 filesystem 文件夹,它用于存储未与数据库关联的通用文件。
为了接收文件,本示例演示如何将 POST 服务中发送的文件直接存储到 Storage:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 文件 = _req.getFile("文件");
_storage.filesystem("服务器", "上传").ensurePath();
文件.save(_storage.filesystem("服务器", "上传", 文件.name()));
const 文件 = _req.getFile("文件");
_storage.filesystem("服务器", "上传").ensurePath();
文件.save(_storage.filesystem("服务器", "上传", 文件.name()));
文件 = _req.getFile("文件")
_storage.filesystem("服务器", "上传").ensurePath()
文件.save(_storage.filesystem("服务器", "上传", 文件.name()))
文件 = _req.getFile("文件")
_storage.filesystem("服务器", "上传").ensurePath()
文件.save(_storage.filesystem("服务器", "上传", 文件.name()))
val 文件 = _req.getFile("文件")
_storage.filesystem("服务器", "上传").ensurePath()
文件.save(_storage.filesystem("服务器", "上传", 文件.name()))
final 文件 = _req.getFile("文件")
_storage.filesystem("服务器", "上传").ensurePath()
文件.save(_storage.filesystem("服务器", "上传", 文件.name()))
文件存储在应用的 storage 文件夹中,路径为:
storage/filesystem/服务器/上传/*
Storage 资源用于获取文件夹和文件路径:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
_storage.filesystem(
"服务器", // filesystem 中子文件夹的名称。
"上传", // 内部子文件夹的名称或路径。
文件.name() // 文件的最终名称。
);
_storage.filesystem(
"服务器", // filesystem 中子文件夹的名称。
"上传", // 内部子文件夹的名称或路径。
文件.name() // 文件的最终名称。
);
_storage.filesystem(
"服务器", # filesystem 中子文件夹的名称。
"上传", # 内部子文件夹的名称或路径。
文件.name() # 文件的最终名称。
)
_storage.filesystem(
"服务器", # filesystem 中子文件夹的名称。
"上传", # 内部子文件夹的名称或路径。
文件.name() # 文件的最终名称。
)
_storage.filesystem(
"服务器", // filesystem 中子文件夹的名称。
"上传", // 内部子文件夹的名称或路径。
文件.name() // 文件的最终名称。
)
_storage.filesystem(
"服务器", // filesystem 中子文件夹的名称。
"上传", // 内部子文件夹的名称或路径。
文件.name() // 文件的最终名称。
)
查看更多 Storage 文档。
要下载文件,本示例演示如何通过 GET 服务获取文件字节:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 文件名称 = _req.getString("文件");
const 文件 = _storage.filesystem(
"服务器",
"上传",
文件名称
).file();
if (文件.exists() == false) {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
);
_exec.stop();
}
_header.downloadFile(文件.name());
_out.copy(文件.input());
const 文件名称 = _req.getString("文件");
const 文件 = _storage.filesystem(
"服务器",
"上传",
文件名称
).file();
if (文件.exists() == false) {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
);
_exec.stop();
}
_header.downloadFile(文件.name());
_out.copy(文件.input());
文件名称 = _req.getString("文件")
文件 = _storage.filesystem(
"服务器",
"上传",
文件名称
).file()
if 文件.exists() == False:
_header.status(404)
_out.json(
_val.map()
.set("结果", False)
.set("错误", "文件不存在")
)
_exec.stop()
_header.downloadFile(文件.name())
_out.copy(文件.input())
文件_名称 = _req.getString("文件")
文件 = _storage.filesystem(
"服务器",
"上传",
文件_名称
).file()
if 文件.exists() == false
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
)
_exec.stop()
end
_header.downloadFile(文件.name())
_out.copy(文件.input())
val 文件名称 = _req.getString("文件")
val 文件 = _storage.filesystem(
"服务器",
"上传",
文件名称
).file()
if (文件.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
)
_exec.stop()
}
_header.downloadFile(文件.name())
_out.copy(文件.input())
final 文件名称 = _req.getString("文件")
final 文件 = _storage.filesystem(
"服务器",
"上传",
文件名称
).file()
if (文件.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
)
_exec.stop()
}
_header.downloadFile(文件.name())
_out.copy(文件.input())
文件夹
我们可以将文件直接保存到计算机上的任意文件夹。
在这种情况下,有两个非常有用的资源:
_app- 可以获取应用中的任意文件夹或文件。_os- 可以获取计算机中的任意文件夹或文件。
查看相应资源 App 和 OS 的文档,这两个资源都有
folder和file方法,分别用于指定文件夹或文件的路径。
为了接收文件,本示例演示如何将 POST 服务中发送的文件直接存储到应用中的某个文件夹:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 文件 = _req.getFile("文件");
const 文件夹 = _app.folder("临时");
if (文件夹.exists() == false) {
文件夹.mkdir();
}
文件.save(_app.file(`临时/${文件.name()}`));
const 文件 = _req.getFile("文件");
const 文件夹 = _app.folder("临时");
if (文件夹.exists() == false) {
文件夹.mkdir();
}
文件.save(_app.file(`临时/${文件.name()}`));
文件 = _req.getFile("文件")
文件夹 = _app.folder("临时")
if 文件夹.exists() == False:
文件夹.mkdir()
文件.save(_app.file(f"临时/{文件.name()}"))
文件 = _req.getFile("文件")
文件夹 = _app.folder("临时")
if 文件夹.exists() == false
文件夹.mkdir()
end
文件.save(_app.file("临时/#{文件.name()}"))
val 文件 = _req.getFile("文件")
val 文件夹 = _app.folder("临时")
if (文件夹.exists() == false) {
文件夹.mkdir()
}
文件.save(_app.file("临时/${文件.name()}"))
final 文件 = _req.getFile("文件")
final 文件夹 = _app.folder("临时")
if (文件夹.exists() == false) {
文件夹.mkdir()
}
文件.save(_app.file("临时/${文件.name()}"))
上面的代码会在应用中创建 临时 文件夹,并将接收到的文件保存到该文件夹中。
要下载文件,本示例演示如何通过 GET 服务获取文件字节:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
const 文件名称 = _req.getString("文件");
const 文件 = _app.file(`临时/${文件名称}`);
if (文件.exists() == false) {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
);
_exec.stop();
}
_header.downloadFile(文件.name());
_out.copy(文件.input());
const 文件名称 = _req.getString("文件");
const 文件 = _app.file(`临时/${文件名称}`);
if (文件.exists() == false) {
_header.status(404);
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
);
_exec.stop();
}
_header.downloadFile(文件.name());
_out.copy(文件.input());
文件名称 = _req.getString("文件")
文件 = _app.file(f"临时/{文件名称}")
if 文件.exists() == False:
_header.status(404)
_out.json(
_val.map()
.set("结果", False)
.set("错误", "文件不存在")
)
_exec.stop()
_header.downloadFile(文件.name())
_out.copy(文件.input())
文件_名称 = _req.getString("文件")
文件 = _app.file("临时/#{文件_名称}")
if 文件.exists() == false
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
)
_exec.stop()
end
_header.downloadFile(文件.name())
_out.copy(文件.input())
val 文件名称 = _req.getString("文件")
val 文件 = _app.file("临时/${文件名称}")
if (文件.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
)
_exec.stop()
}
_header.downloadFile(文件.name())
_out.copy(文件.input())
final 文件名称 = _req.getString("文件")
final 文件 = _app.file("临时/${文件名称}")
if (文件.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("结果", false)
.set("错误", "文件不存在")
)
_exec.stop()
}
_header.downloadFile(文件.name())
_out.copy(文件.input())
结论
如你所见,我们可以将文件上传集成到 REST API 服务中,甚至与 OpenAPI 集成。
我们可以将文件保存到数据库、应用内的 storage 文件夹或计算机上的任意文件夹。
查看本教程中使用的、可用于操作文件的资源文档:
在数据库中,我们可以将图片保存到 image 类型字段,也可以将任意类型的文件保存到 file 类型字段;无论是图片还是通用文件,保存或获取文件的方式在各種情况下都相同。