如何通过AstroZero脚本,导出xls文件让用户下载?
问题描述
AstroZero提供了“excel”脚本标准库,用于操作Excel文件,例如生成Excel文件。由于AstroZero脚本编排的标准输出格式是JSON,因此这里需要做一些特殊处理,让系统生成非JSON数据才能实现xlsx文件导出。
操作步骤
- 参考开发一个简单脚本实例中操作,创建一个名称为“cube__download”的空白脚本。
- 在脚本编辑器中,输入如下脚本代码。
import * as excel from 'excel'; import * as context from 'context'; import * as buffer from 'buffer'; export class Downlaod { @action.method({ input: "Input", output: "Output", description: "do a operation" }) run(): void { // 原始数据,可以从数据表中获取,此处为了演示方便,使用静态数据 let binary = excel.encode(['a', 'b', 'c'], [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }, { 'a': 7, 'b': 2, 'c': 3 }]); // 对于 Excel2007 以上版本的 .xlsx 文件,需要设置内容类型为 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet context.getHttp().response.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64'); // 直接把二进制作为请求体返回 context.getHttp().response.setBody(buffer.fromBytes(binary).toString(buffer.Encoding.Base64)); } }
此时,后端返回了一个base64编码的二进制数据,并非JSON格式,所以直接运行脚本不会有输出,需要在前端页面匹配处理这种数据才行。
- 在标准页面上,调用“cube__download”脚本。
为了简化配置,此处没有把脚本封装为公共接口,实际使用时业务应该使用公共接口进行封装,以便实现更细粒度的权限控制。
以jQuery的ajax方法为例,代码示例如下:
var url = "/u-route/baas/script/v1.0/run/cube__download"; context.$utils.getCSRFToken().then(function(token) { $.ajax({ type: "POST", headers: { 'Content-Type': "application/json", 'responseType':"arraybuffer", 'csrf-token': token, }, url: url, data: JSON.stringify({}), dataType: 'text', async: false, success: function(resp){ var fileName = "test" + '.xlsx'; var file = new Blob([s2ab(atob(resp))], {type: ''}); if (window.navigator.msSaveOrOpenBlob) { //IE浏览器下载 window.navigator.msSaveOrOpenBlob(file, fileName); } else { var fileUrl = URL.createObjectURL(file); var a = document.createElement('a'); a.href = fileUrl; a.target = '_blank'; a.download = fileName; document.body.appendChild(a); a.click(); } }, error: function(resp){ } }); });
“s2ab()”是数据处理的关键,这个方法名字是“string to array buffer”的缩写,意思是把字符串转换为ArrayBuffer类型,以便让前端可以处理二进制数据。其函数定义如下:
function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i=0; i!=s.length; ++i) { view[i] = s.charCodeAt(i) & 0xFF; } return buf; }
上述代码中,需要注意如下事项:
- Header里面需要增加'responseType':"arraybuffer";
- Header里的类型为dataType: 'text';
- Header里增加csrf-token。
应用后端开发 所有常见问题
- 如何区分不同账户间的数据库对象?
- 在AstroZero对象中删除字段重建后,引用的地方报错
- 如何刷新AstroZero对象的布局页面?
- 如何彻底删除AstroZero对象目录树中的数据?
- AstroZero系统预置的owner字段,用于记录什么用户?
- AstroZero脚本中可使用哪些资源?
- AstroZero脚本编写只支持TS,不支持JS吗?
- 在AstroZero脚本中执行sql语句时,可以不用@useObject修饰数据对象吗?
- 在AstroZero脚本中,如何返回zip压缩文件内容?
- 如何通过AstroZero脚本,导出xls文件让用户下载?
- AstroZero脚本中是否支持multipart/form-data请求?
- AstroZero服务编排中涉及数据操作的脚本图元,在其他图元操作失败的情况下,是否可以回滚?
- 事件触发的AstroZero服务编排,发送事件后,服务编排没有运行?
- 在AstroZero服务编排、工作流中,引用的资源无法编辑
- 如何实现某一资源被多个AstroZero应用的服务编排调用?
- 在AstroZero服务编排中,可以跨应用引用资源?
- 在AstroZero服务编排、工作流或脚本中,邮件发送功能不可用?
- AstroZero开发者如何使用自己的邮箱发送邮件?
more