具体场景
以私钥的输入为例,用户既可以直接输入私钥内容,也可以上传指定的文件。
如何实现
用 tabs 或 select 控件自由切换输入/上传方式,是 AMis 推荐的模式。
{
"type": "button",
"label": "新增",
"level": "primary",
"className": "m-r-xs",
"behavior": "Insert",
"onEvent": {
"click": {
"actions": [
{
"actionType": "dialog",
"dialog": {
"type": "dialog",
"title": "新增数据",
"body": [
{
"id": "u:2b9e1961e997",
"type": "form",
"title": "新增数据",
"mode": "flex",
"labelAlign": "top",
"dsType": "api",
"feat": "Insert",
"body": [
{
"name": "name",
"label": "name",
"row": 0,
"type": "input-text",
"id": "u:649fb9d93c2e"
},
{
"type": "select",
"label": "pem私钥输入方式",
"name": "input_mode",
"row": 1,
"options": [
{
"label": "直接输入",
"value": "text"
},
{
"label": "上传文件",
"value": "file"
}
],
"id": "u:edd5de2054f4",
"multiple": false,
"size": "sm",
"selectFirst": true
},
{
"type": "textarea",
"label": "pem私钥",
"name": "private_key_pem",
"row": 2,
"colSize": "1",
"id": "u:2bb518c4e0cc",
"minRows": 3,
"maxRows": 20,
"visibleOn": "${input_mode=== 'text'}"
},
{
"type": "input-file",
"label": "pem私钥文件上传",
"autoUpload": true,
"proxy": true,
"uploadType": "asForm",
"name": "private_key_pem_file_asbase64",
"row": 3,
"colSize": "1",
"id": "u:5ba0338375fe",
"btnLabel": "文件上传",
"multiple": false,
"useChunk": false,
"accept": "",
"drag": false,
"asBlob": false,
"asBase64": true,
"formType": "asBase64",
"onEvent": {},
"visibleOn": "${input_mode==='file'}"
},
{
"name": "description",
"label": "描述",
"row": 4,
"type": "input-text",
"id": "u:be1465a0b2ee"
}
],
"resetAfterSubmit": true,
"actions": [
{
"type": "button",
"actionType": "cancel",
"label": "取消"
},
{
"type": "button",
"actionType": "submit",
"label": "提交",
"level": "primary"
}
],
"onEvent": {
"submitSucc": {
"actions": [
{
"actionType": "search",
"groupType": "component",
"componentId": "u:86eeb4c2dc51"
}
]
}
}
}
],
"size": "md",
"actions": [
{
"type": "button",
"actionType": "cancel",
"label": "取消",
"id": "u:f4d7b414e7b1"
},
{
"type": "button",
"actionType": "submit",
"label": "提交",
"level": "primary",
"id": "u:3cd978b191bd",
"onEvent": {
"click": {
"weight": 0,
"actions": [
{
"ignoreError": false,
"outputVar": "responseResult",
"actionType": "ajax",
"options": {},
"api": {
"url": "/admin/cloud/v1/rsa_add",
"method": "post",
"requestAdaptor": "if (!(api.data.private_key_pem) && api.data.private_key_pem_file_asbase64) {\n console.log(api.data.private_key_pem_file_asbase64);\n base64 = api.data.private_key_pem_file_asbase64.split(',')[1];\n api.data['private_key_pem'] = atob(base64);\n}\n\nreturn api;",
"adaptor": "",
"messages": {},
"dataType": "json",
"data": {
"name": "${name}",
"private_key_pem": "${private_key_pem}",
"private_key_pem_file_asbase64": "${private_key_pem_file_asbase64}",
"description": "${description}"
}
}
}
]
}
}
}
],
"actionType": "dialog",
"id": "u:af133b5ba74c",
"showCloseButton": true,
"closeOnOutside": false,
"closeOnEsc": false,
"showErrorMsg": true,
"showLoading": true,
"draggable": false
}
}
]
}
},
"id": "u:5bd82685f6b5"
}
InputFile 文件上传: 作为表单项上传
实现细节
- 通用流程
AMis 表单设计成不管用户上传文件还是直接输入,最终都将 SSH 的内容(文本)作为字符串字段提交给后端,那么后端只需要接受一个字符串参数就可以(比如 JSON 字段 ssh_private_key 或类似)。这种方式最简单,后端无需区分来源。
通用流程如下:
- 用户上传文件 → 前端用 JS 读取文件内容为字符串 → 填充到表单的字符串字段
- 用户直接输入 → 也是同一个表单字符串字段
- 提交时都是同一个参数
服务端只需接收字符串,只要能处理好 SSH 密钥的内容即可,不额外修改上传文件相关逻辑。
- 发送适配器
function(api, context) {
if (!(api.data.private_key_pem) && api.data.private_key_pem_file_asbase64) {
base64 = api.data.private_key_pem_file_asbase64.split(',')[1]; // 获取 base64
api.data['private_key_pem'] = atob(base64);
}
return api;
}
作为表单项上传,配置数据格式为 asBase64 ,实际上得到的是Data URL格式(而不是只包含纯base64字符串),一般形如:
data:MIME类型;编码,data
举个例子:
data:application/x-x509-ca-cert;base64,CgotLS0tLUJFR0l...
data:
说明后面这是一个 Data URLapplication/x-x509-ca-cert
: MIME 类型,指明数据的文件类型,本例是 x509 CA 证书base64
: 后面的数据使用了 base64 编码,
分隔,后面是真正的 base64 字符串CgotLS0tLUJFR0l...
这是真正的原始数据经过 base64 编码后的部分
这种格式的目的是为了让浏览器在某些场合,可以直接把 base64 数据作为图片、文件、Blob、下载资源等直接使用,而不需要另外上传到服务器。
为什么不是直接输出 Base64?
如果只返回纯 base64 内容,那么你拿到的字符串只有:
CgotLS0tLUJFR0l...
这样你无法得知这是什么文件、什么类型,也难以直接用在 HTML 的 src/href
属性等需要完整 Data URL 格式的地方。
有了前缀(Data URL)之后你可以:
- 直接赋值给
<img src="这里">
- 立即 start 下载,比如
<a download href="这里">
- 方便前端使用 fileType 或内容类型解析
总结
带上这些前缀是为了让数据格式自描述,更方便前端使用和处理!
Comments