天天看点

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

Jerry 之前发布过一篇文章 不使用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器,之后不少朋友留言,提出的问题概括为以下两类:

(1) 客户端通过 multipart/form-data 格式发送的数据,ABAP 端除了像 Jerry 文章采取字符串解析这种比较繁琐的方式处理外,还有其他方法吗?

(2) 能否上传二进制文件比如 Excel 到 ABAP 并进行解析?

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

本文就来解答这两个问题。

使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器

关于 multipart/form-data 格式的详细说明,参考 Mozilla 开发社区和 W3 Org 的文档:

  • https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
  • https://www.w3.org/html/wg/spec/association-of-controls-and-forms.html#multipart-form-data

我在前文例子的基础上稍作修改,在 Form 里使用两个类型为 file 的 input 标签,分别上传 PDF 和 Excel 文件:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件
使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

用来测试的本地 PDF 文件:PDF.pdf,大小为 30129 字节。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

内容如下:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

本地用来测试的 Excel 文件:TEST.xlsx,内容如下:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

点击 HTML 页面上传文件的超链接,在 Chrome 开发者工具观察到 HTTP POST 请求的负载,包含了 PDF 和 Excel 两个 input 控件包含的二进制流(stream):

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

点击 view source,查看 multipart/form-data 数据明细:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

我们仍然可以在 Chrome 开发者工具里观察到上传的 PDF 和 Excel 的文件名和 Content-Type 即文件类型。同前文上传文本文件的例子不同,这里无法看到两个文件的二进制内容——这些二进制内容可以在 ABAP 服务器端调试器里观察到。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

以上传的 PDF 文件为例,在 ABAP 服务器端接收到的 form-data 数据,如下图所示,绿色高亮区域即为上图 Chrome 开发者工具里能够观测到的文件名 PDF.pdf 和文件类型 application/pdf, 而%PDF-1.4# 开头的,就是 PDF 文件的二进制内容。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

准确的说,PDF 格式是文本和二进制流的混合模式。用文本编辑器打开 PDF.pdf, 能看到其文件头部包含的是文本字符描述的文件元数据,比如该文件的创建和修改时间,创建该文件的工具名等等,后半部分才是二进制流。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

现在已经有很多开源工具比如 JavaScript 库可以用来生成和解析 PDF 文件了,感兴趣的朋友可以在搜索引擎里搜索 Jerry 这几篇文章:

  • 使用 ABAP 和 JavaScript 代码生成 PDF 文件的几种方式
  • 使用 JavaScript 将当前页面保存成 PDF,支持图片和文字的保存
  • PDF 文件如何转成 markdown 格式

对于上传到 ABAP 服务器的 PDF 文件的文件名,我们仍然采取和前一篇文章同样的方式解析,从下图红色矩形框中的字符串中提取。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

而对于上图绿色高亮的 PDF 的二进制数据,CL_HTTP_REQUEST 提供了相应方法来提取。关键代码如下图所示:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

当 ABAP 服务器接收到的客户端数据格式为 multipart/form-data 时,调用 CL_HTTP_REQUEST 的num_multiparts 方法可以得到 parts 的个数,再使用 get_multipart 方法,传入每个 part 的索引,就可以得到代表这个 part 的一个实例引用。

调用该引用的get_content_type 和 get_data 方法,就能解析出上传文件的类型(比如 pdf 格式对应的 application/pdf)和二进制内容。

至此调用 SAP CRM 附件创建 API 的三大参数:文件名,文件类型和文件二进制内容均已就绪,调用 API 即可将上传的 PDF 和 Excel 数据,创建成为 SAP CRM 销售订单的附件。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

创建好的 PDF 和 Excel 附件在 SAP CRM 系统里显示如下:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

打开这两个附件,确保上传之后,其内容同本地文件完全一致:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

如何使用 ABAP 解析上传的 Excel 文件

这个话题,其实 Jerry 2019 年的文章 使用ABAP操作Excel的几种方法 已经系统介绍过。

我们在 ABAP 调试器里观察到,本地扩展名为 xlsx 的 Excel 文件,上传到 ABAP 服务器时,其 content-type 为:

application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

什么是 openxmlformats?下面通过具体的例子来说明。

以我这个本地 Excel 文件为例,将扩展名从 xlsx 更改为 zip,然后解压:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

发现 xlsx 文件其实是一个压缩包,解压之后生成了一个文件夹,包含了下图所示的若干子文件夹和文件。

上图 Excel 文件有一个名为 Sheet1 的内容页,A1 值为 ABAP,B1 值为 Java,这个信息维护在解压出来的 worksheets 文件夹的子文件 sheet1.xml 内:

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

上图高亮的 XML c 节点代表 Cell,r=“A1” 和 r=“B1”, 代表这两个 cell 所在的 Row ID,c 的子节点 v 包含了 Cell 的具体值。

不难发现,sheet1.xml 里并未直接将 ABAP 和 Java 的字符串字面量在内,而仅仅存放了其索引,0 和 1. 做过 Java 开发的朋友,可以把这种设计类比成 Java 的字符串常量池。

在解压出的文件夹里有另一个文件 sharedStrings.xml, 顾名思义,维护了 Excel worksheets 里出现的所有字符串,用于在 sheets 之间共享。每个单独的 sheet xml 文件只维护使用到的字符串的索引,以减小 Excel 文件的尺寸。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

因此,只要熟悉了 TEST.xlsx 重命名为 TEST.zip 并解压之后生成的每一个文件的用途,即 Open XML Formats 的协议规范,就可以使用任何高级编程语言解析 Excel 文件。

可以在 WikiPedia 里找到 Open XML Formats 协议定义的每个文件的作用:

https://en.wikipedia.org/wiki/Office_Open_XML_file_formats

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

SAP CRM 提供了一个工具类,基于 Open XML Formats 解析 Excel 文件内容:cl_xlsx_document.

只需将 Excel 文件的二进制内容传入,该工具类即返回一个 Excel 文件的引用,根据该引用的各种 GET 方法,即可访问到 Excel 文件内由 Open XML Formats 协议定义的各个部分的内容。

核心逻辑如下图所示,代码都是自描述的,这里不再赘述。

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

当然,开源项目 abap2xlsx 也是另一个选择:

https://github.com/sapmentors/abap2xlsx

使用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析使用 JavaScript 通过 multipart/form-data 格式发送 PDF 和 Excel 文件到 ABAP 服务器如何使用 ABAP 解析上传的 Excel 文件

至于 SAP Fiori 应用通过 SAP Gateway 上传附件的技术细节,Jerry 将来会介绍。

本文涉及到的前后端完整源代码,请在这个链接处下载。

感谢阅读。