对接第三方OCR服务开发笔记

在最近的工作中,有对接第三方OCR服务的需求,经过一番捣鼓后,终于调试通了,在此记录下开发过程的心得体会。

需求北京说明

项目中用到OCR识别功能,用于识别图片中的信息,解析后导入到系统。该功能由第三方以RestFul API的形式提供,接口要求以POST方式提供图片的base64编码结果。

demo搭建

最开始,自己通过画图工具,构造了一些图片,然后在 base64图片在线转换这里进行编码,获取右侧的字符串后,通过

curl -X POST -d"image=base64code" url

的方式测试,发现返回500错误,通过询问第三方技术人员后发现是编码串的问题,通过和他们提供的测试串进行对比,发现以下区别:

网页工具生成的base64字符串的格式为:

data:image/jpg;base64,XXX

前面的都是生成串的格式说明,后面的XXX才是实际编码内容串。通过更换编码字符串后,继续测试,还是返回500错误,这下又疑惑了。进一步沟通,发现那边是使用Postman工具来对接口进行测试,顺便学习了Postman工具,然后进行测试,并且与curl命令行测试的结果进行对比,发现通过Postman发送的POST请求时,针对数据有以下四种传输类型:

  • form-data: 将表单数据组织成key-value形式的一条消息,既可以上传键值对,也可以上传文件。
  • x-www-form-urlencoded:将传输数据进行urlencoded编码,只可以上传键值对。
  • raw:传递txt、json、xml、html等原始数据
  • binary:只支持上传单个二进制数据

测试工具Postman中,POST发送的四种数据类型区别点此查看

言回正传,调试不同,初步怀疑是Url编码问题。查看curl的自带的帮助,找到如下说明:

对接第三方ORC服务开发笔记-curl的POST说明文档.jpg

通过上面说明,可以知道:

  • -d/--data:-d格式后面可以紧跟数据,也可以间隔一个空格。--data后面必须间隔空格。默认文件内容格式为 application/x-www-form-urlencoded,表示传输内容已经经过url编码,那么要求使用者需要自行编码后再传入。
  • --data-ascii:同 --data 是一回事
  • --data-binary:对上传数据不做任何处理,适合上传二进制数据,支持从文件中读取数据(@filename),保留回车和换行字符。
  • --data-raw:同--data一样,但不会解析@字符。
  • --data-urlencode: 对post的数据进行url encoded

带着问题深入curl

带着以下两个问题,深入curl源码来了解。

  • -d选项对应的处理源码在哪里?
  • --data-urlencode是哪个版本引入的,具体是如何处理?

curl针对同类型选项,有一个映射缩写表:

  {"d",  "data",                     ARG_STRING},
  {"dr", "data-raw",                 ARG_STRING},
  {"da", "data-ascii",               ARG_STRING},
  {"db", "data-binary",              ARG_STRING},
  {"de", "data-urlencode",           ARG_STRING},

由上表可见,--data--data-urlencode 都是在命令行处理函数的 getparameter中的case d分支处理,--data-urlencoded分支中的e子分支继续处理。

tool_getparam.c
ParameterError getparameter(...)
{
	// ... --data-urlencode 

	char letter = 'd';
    char subletter = 'e';
	char* nextarg; // 指向POST的数据指针 eg:value=123
	switch(letter) {
		case 'd':
		{
			if(subletter == 'e') {
				const char *p = strchr(nextarg, '=');
				size_t size = strlen(p);
				char *enc = curl_easy_escape(NULL, postdata, (int)size);
			}

			// 将处理好的POST数据填入config
			config->postfields = enc;
    		config->postfieldsize = size;
		}
	}
} 


由上述截取的源码片段可知,--data-urlencode使用curl_easy_escape对post数据进行url编码,而--data则没有编码,此功能在7.18.0版本中引入的。

特别提示:

使用curl的post功能时,如果POST的数据较长,不方便放在命令行中,可以将POSt数据存放在文件中,通过如下命令来发送:

curl --data-urlencode @file_path url

注意点:

  1. 当从文件中读取post内容时,请求数据中不在需要“=”号,如果有key的话,可以也要写到文件中.
  2. file_path可以用绝对路径,也可以用相对路径。当使用相对路径时,是相对于程序运行目录.
  3. file_path左右不需要加上引号

概要设计

通过前期的需求分析,此任务可划分为以下子任务:

  • 加载图片
    • 支持图片选择和拖拽
    • 支持图片预览
    • 图片有效性判断
  • OCR图片解析
    • 调用第三方API接口
    • 解析过程的提示
    • 异常情况处理
      • 中途退出
      • 解析超时
      • 解析响应错误
    • 处理正常解析结果

开发过程中的注意事项

该功能是在原有导入功能上新增的导入方式,解析输出结果要和其他导入方式相一致。

在发送POST请求时,由于之前是通过curl来发送,实现时,自然而然通过已有的curl组件来发送请求,初版提交后经同事审阅,需要使用该模块统一的数据请求通道,而不是通过curl来发送,理由有下:

  1. 走统一数据请求通道,数据在传输过程中是加密的,安全性有保证。
  2. 只需要传解析地址的路径即可,不需要传完整url,由后端统一处理测试环境和生产环境的差异。
  3. 有统一的日志记录和采集分析,如果是自己发送,则日志无法在中台留痕,不利于分析问题。

在新增功能时,时刻注意,不能因为优化重构,而影响原有功能。最好准备两份代码,一份开发新功能,另一份用于对比旧功能,保证同样的操作,新旧版本上现有功能不受影响。很多时候的重构优化,改多了会忘记现在这个情况是原有就有的,还是改动带来的优化,一定要注意,小步慢跑,稳步推进。

在开发完成后,提交之前,多看看自己写的代码,哪些变量和函数可以去掉,哪些地方可以减少拷贝操作,哪些命名还可以优化的。看完一片后,可以过一天,再继续看,总会有优化空间的。

提交到版本库中的配置,应该都是生产时的配置,不要将debug版本的配置提交上去。

小结

本文小结了对接第三方OCR服务过程中的心得体会,以飨读者。

posted @ 2021-09-24 14:08  浩天之家  阅读(434)  评论(0编辑  收藏  举报