• 对接第三方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服务过程中的心得体会,以飨读者。

    作者:浩天之家
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
    Top
    收藏
    关注
    评论
  • 相关阅读:
    讨论: 在WebControl中的Button,同时有onClientClick和onclick事件,验证控件实效
    在DropDownList中显示树形结构
    我的软件开场白+简单的通讯录
    DataList中动态添加控件遇到的问题
    伤心啊!不知道怎么感冒了
    存储过程实现无限级分类(2)
    上传文件类
    一个用泛型,和Sql语句分页的源代码
    在GridView中用Js实现全选
    [转]如何完美应对面试
  • 原文地址:https://www.cnblogs.com/cherishui/p/15330128.html
Copyright © 2020-2023  润新知