不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

采用 SAP UI5 sap.ui.unified.FileUploader 控件,结合 Gateway 框架,实现本地文件上传到 ABAP 服务器,不是一件困难的事情。

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

但由于项目实施的客观条件限制,如果不使用 SAP UI5 和 SAP ABAP Gateway 这两个框架,又该如何实现呢?


这是最近一个朋友咨询我的问题。实际上我早在 2014 年就做过类似的事情。本文介绍不使用 SAP UI5 和 SAP ABAP Gateway 框架,纯手工进行前后端编程,来实现文件上传的需求步骤。


本文提供的源代码,前端 JavaScript 代码和 后端 ABAP 服务器的文件接收代码,由于没有使用任何应用层面的框架,因此能够在 SAP 任何基于 ABAP 技术栈的 On-Premises 产品里运行。


我们从前后端两层的实现来分别了解这个需求的实现细节。


前端实现

前端代码比较简单,只有 30 行代码。新建一个 HTML 文件,把这 30 行代码粘贴进去。


其设计思路概述成以下 7 点。需要完整源代码的朋友,请从这个链接获得。


(1) 定义一个原生的 form 元素,使用 enctype 字段指定该表单发送到服务器的编码格式为 multipart/form-data.


(2) 该表单的数据使用 HTTP POST 方法发送到服务器。


(3) 表单里包含了三个 input 控件,类型分别为 email, text 和 file. 本文介绍的本地文件上传功能,就是借助第 8 行类型为 file 的 input 控件来完成的。点击第 11 行用 a 标签实现的超链接后,绑定到 a 标签的 sendForm 函数触发,进行数据发送工作。

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

(4) 将 form 表单里全部数据通过 DOM API document.forms.namedItem 解析出来,放入变量 oData.


(5) 第 17 行语句演示了通过代码的方式,往待发送往服务器的表单数据里,再添加新内容的方法。


(6) 该行维护了表单数据发送到 ABAP 服务器的具体地址,其 SICF 路径为 /sap/crm/file_upload.


文件上传到 ABAP 服务器后,我们如何验证上传是否成功,内容是否正确呢?出于验证目的,我硬编码了一个销售订单 ID 55824.文件上传成功后,我在 SAP CRM 系统里,将上传的文件创建为该销售订单的一个附件。


(7) 调用原生 API XMLHttpRequest 的 send 方法,把表单数据传送到 ABAP 服务器。

打开这个 HTML 文件,如下图所示,点击超链接进行文件上传。

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

ABAP 后端实现

因为我们不借助任何后端框架,这意味着我们必须基于最底层的 HTTP 协议,自行解析出客户端发送过来的 multipart/form-data 格式的数据并进行处理。

首先在事物码 SICF 里,根据前端代码里的路径 sap/crm/file_upload, 新建一个同样路径的处理节点。

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

完整的后端代码同样能从这个链接获得,本文不全部贴出,只介绍要点。

通过前端 form 表单三个 input 控件维护的输入值,加上前端代码中自定义的表单数据,被浏览器随机生成的 FormBoundary 所分隔。提交表单的完整数据,能够在 Chrome 开发者工具 Network 标签页里观察到。

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

因此,我的思路就是,根据回车换行符定位到上图 ABAP 变量 LV_DATA 包含的 form-data 块,如果该块包含了 content-type:text/plain,就说明此块包含的是上传文件的实际内容,对其解析即可得到上传文件的实际内容。

这里不少新手朋友们常犯的错误是,因为在 ABAP 调试器里观察到的回车换行符显示为“##”,因此在代码里,这些朋友也直接用单井号或者双井号进行字符串匹配,这当然无法工作。

在 ABAP 里要进行和换行符以及回车换行符相关操作,需要使用 ABAP 工具类 CL_ABAP_CHAR_UTILITIES 定义的常量:CR_LF 和 NEWLINE:

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

解析出上传的文本文件内容后,调用 SAP CRM 附件创建 API,将该文件内容作为一个附件,添加到系统 ID 为 55824 的销售订单中去。


本例为了简化起见,只支持类型为文本(text/plain)的本地文件上传成销售订单(其 BOR 类型为 BUS20000115)的附件,故文件类型和 BOR 类型都进行了硬编码。

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

点击附件超链接,打开该文件内容,发现和本地文件完全一致,测试通过:

不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器

当然,本文描述的实际是一个重新造*的场景。大家在实际项目开发中,如果没有特殊原因,还是尽量采用 SAP 提供的现成框架和工具,来完成诸如文件上传这种比较基础和底层的工作,从而把精力放到业务逻辑的编写中去。


感谢阅读。


Jerry 的 ABAP 专题


Jerry的ABAP, Java和JavaScript乱炖


ABAP开发人员未来应该学些什么


Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现


Jerry的ABAP原创技术文章合集


300行ABAP代码实现一个最简单的区块链原型


使用Java+SAP云平台+SAP Cloud Connector调用ABAP On-Premise系统里的函数


在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务


ABAP vs Java, 蛙泳 vs *泳


聊聊C语言和ABAP


动手使用ABAP Channel开发一些小工具,提升日常工作效率


我用ABAP做过的那些无聊的事情


不喜欢SAP GUI?那试试用Eclipse进行ABAP开发吧


使用Visual Studio Code编写和激活ABAP代码


你的ABAP程序给佛祖开过光么?来试试Jerry这个小技巧


在SAP云平台ABAP编程环境上编写第一段ABAP程序


SAP官方发布的ABAP编程规范


ABAP Code Inspector那些隐藏的功能,您都知道吗?


还在用ABAP进行SAP产品的二次开发?来了解下这种全新的二次开发理念吧


ABAP Netweaver体内的那些寄生式编程语言


从SAP社区上的一篇博客开始,聊聊SAP产品命名背后的那份情怀


云端的ABAP Restful服务开发


如何在SAP云平台ABAP编程环境里把CDS view暴露成OData服务


使用abapGit在ABAP On-Premises系统和SAP云平台ABAP环境之间进行代码传输


30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用


Jerry带您了解Restful ABAP Programming模型系列之二:Action和Validation的实现


Jerry带您了解Restful ABAP Programming模型系列之三:云端ABAP应用调试


SAP云平台上的ABAP编程环境里如何消费第三方服务


ABAP开发者上云的时候到了 - 现在大家可以免费使用SAP云平台ABAP环境的试用版了


学而不思则罔 - SAP云平台ABAP编程环境的由来和适用场景


SAP云平台里的三叉戟应用


如何基于Restful ABAP Programming模型开发并部署一个支持增删改查的Fiori应用


SAP 2019 TechEd Key Note解读:云时代下SAP从业人员如何做二次开发?


有哪些ABAP关键字和语法,到了ABAP云环境上就没办法用了?


ABAP开发环境终于支持以驼峰命名法自动格式化ABAP变量名了


利用ABAP 740的新关键字REDUCE完成一个实际工作任务


一段让人瑟瑟发抖的ABAP代码


昨日万圣节ABAP怪兽级代码谜团,公布答案啦


介绍一种在ABAP内核态进行内表高效拷贝的方法


使用SAP Cloud Application Programming模型开发OData的一个实际例子


当ABAP遇见普罗米修斯


使用ABAP绘制可伸缩矢量图


ABAP开发环境语法高亮的那些事儿


SAP错误消息调试之七种武器:让所有的错误消息都能被定位


使用ABAP操作Excel的几种方法


SAP GUI里的收藏夹事务码管理工具


SAP GUI和Windows注册表


有了Debug权限就能干坏事?小心了,你的一举一动尽在系统监控中


ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX这些东东是什么鬼


实现ABAP条件断点的三种方式


使用SAT跟踪监控从浏览器打开的SAP应用的性能和调用栈


一个13年ABAP老兵的建议:了解这些基础知识,对ABAP开发有百利而无一害


SAP ABAP Netweaver容器化, 不可能完成的任务吗?


SAP产品增强技术回顾


SAP API开发方法大全


浅谈Java和SAP ABAP的静态代理和动态代理,以及ABAP面向切面编程的尝试


SAP ABAP应用服务器的HTTP响应状态码(Status Code)


SAP ABAP里存在Java List这种集合工具类么?CL_OBJECT_COLLECTION了解一下


ABAP面试题系列:写一组会出现死锁(Deadlock)的ABAP程序


SAP ABAP Netweaver服务器的标准登录方式讲解


SAP ABAP关键字语法图和ABAP代码自动生成工具Code Composer


SAP ABAP SM50的另类用途 - ABAP工作进程对数据库表读取操作的检测


关于SAP ABAP字符变量和字符串变量字符个数的一个知识点,和一个血案


SAP ABAP一组关键字 IS BOUND, IS NOT INITIAL和IS ASSIGNED的用法辨析


SAP ABAP和Java里的弱引用(WeakReference)和软引用(SoftReference)


SAP AMDP介绍 - ABAP托管的HANA数据库过程


给你的ABAP对象打上标签(Tag)


历史上的今天:编程语言中null引用的十亿美元错误


ABAP Development Tool 代码模板和其他一些实用技巧汇总


SAP ABAP Development Tool 提高开发效率的十个小技巧


如何在 SAP BTP 平台 ABAP 编程环境里消费基于 SOAP 的 Web Service


ABAP 真的会过时吗?聊聊 ABAP 的过去,现在和未来


基于 abapGit 和 abaplint 的 ABAP 持续集成的一个例子

上一篇:基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET平台开发指南 - 处理报表


下一篇:北航教授蔡维德:交易频率超8000次/秒的区块链是怎样炼成的 | GAIR 2017