SDK隐私政策
							
							Hi,您好,欢迎使用有道智云自定义模版文字识别 API 接口服务。
本文档主要针对需要集成 API 的技术开发工程师,详细描述自定义模版文字识别能力相关的技术内容。
如果您有与我们商务合作的需求,可以通过以下方式联系我们:
商务邮箱: AIcloud_Business@corp.youdao.com
如果您对文档内容有任何疑问,可以通过以下几种方式联系我们:
客服 QQ:1906538062
智云 OCR 技术交流 QQ 1 群: 654064748
智云 OCR 技术交流 QQ 2 群: 471638046
联系邮箱: zhiyun@corp.youdao.com
温馨提示:
本文档主要针对开发人员,接入测试前需要获取应用ID和应用密钥;如果您还没有,请按照 新手指南 操作。
平台向每个账户赠送 50 元的体验金,供用户集成前测试所用,具体资费规则详见 自定义模版文字服务报价 。
自定义模板文字识别 API HTTPS 地址:
https://openapi.youdao.com/iocr
调用方在集成自定义模板文字识别 API 时,请遵循以下规则。
| 规则 | 描述 | 
|---|---|
| 传输方式 | HTTPS | 
| 请求方式 | POST | 
| 字符编码 | 统一使用 UTF-8 编码 | 
| 请求格式 | 表单 | 
| 响应格式 | JSON | 
调用 API 需要向接口发送以下字段来访问服务。
| 字段名 | 类型 | 含义 | 必填 | 备注 | 
|---|---|---|---|---|
| q | text | 待识别图像 Base64 | True | 必须是 Base64 编码 | 
| templateId | text | 模版 Id | false | 模版 Id。当generalOcr为true时,该字段可以为空 | 
| format | text | 图片类型填写'img',pdf填写'pdf' | False | 默认img | 
| appKey | text | 应用 ID | True | 可在 应用管理 查看 | 
| salt | text | UUID,和 curtime 一起防请求重放 | True | uuid,唯一通用识别码 | 
| signType | text | 签名类型 | True | v3 | 
| curtime | text | 当前 UTC 时间戳(秒) | True | TimeStamp | 
| sign | text | 签名 | True | sha256(应用 ID+input+salt+curtime+应用密钥) | 
| generalOcr | text | 是否包含通用OCR结果 | false | 默认false。如果为true,结果中会包含通用OCR结果 | 
签名生成方法如下: signType=v3; sign=sha256(
应用ID+input+salt+curtime+应用密钥)。 其中,input 的计算方式为:input=q前10个字符+q长度+q后10个字符(当 q 长度大于 20)或input=q字符串(当 q 长度小于等于 20)。
如果对签名有疑问,可以参看文档末尾各语言 demo。
返回的结果是 json 格式,具体说明如下
| 字段名 | 类型 | 字段说明 | 
|---|---|---|
| errorCode | text | 错误码,一定存在 | 
| Result | text | 识别结果,查询成功一定存在 | 
| +template_id | text | 模版Id | 
| +items | JSONObject | 字段名称及识别结果 | 
| ++识别区域信息 | text | 识别内容,识别成功一定存在 | 
识别的返回结果:
{
  "errorCode": "0",
  "Result": {
    "template_id": "模版Id",
    "items": [
        {
          "key": "字段名称",
          "value": "字段值",
          "locations": ["坐标信息"] // 如果有多区域同名,坐标会有多行,对应多个区域的坐标
        },
    ]
    "ocrResult": {
        // 通用OCR结果
    }
  }
}
| 语言代码 | 语言 | 
|---|---|
| sq | 阿尔巴尼亚语 | 
| az | 阿塞拜疆语 | 
| eu | 巴斯克语 | 
| be | 白俄罗斯语 | 
| bs | 波斯尼亚文(拉丁文) | 
| bg | 保加利亚文 | 
| ca | 加泰罗尼亚文(加泰隆语) | 
| ceb | 宿务语 | 
| ny | 齐切瓦语 | 
| zh-CHS | 中文 | 
| zh-CHT | 中文(繁体) | 
| co | 科西嘉语 | 
| hr | 克罗地亚文 | 
| cs | 捷克文 | 
| da | 丹麦文 | 
| nl | 荷兰文 | 
| en | 英文 | 
| eo | 世界语 | 
| et | 爱沙尼亚文 | 
| fi | 芬兰文 | 
| fr | 法文 | 
| gd | 苏格兰盖尔语 | 
| gl | 加利西亚语 | 
| de | 德文 | 
| ht | 海地文 | 
| ha | 豪萨语 | 
| haw | 夏威夷语 | 
| hi | 印地文 | 
| hu | 匈牙利文 | 
| is | 冰岛语 | 
| ig | 伊博语 | 
| id | 印度尼西亚文 | 
| ga | 爱尔兰语 | 
| it | 意大利文 | 
| ja | 日文 | 
| jw | 印尼爪哇语 | 
| ko | 韩文 | 
| ku | 库尔德语 | 
| la | 拉丁语 | 
| lv | 拉脱维亚文 | 
| lt | 立陶宛文 | 
| lb | 卢森堡语 | 
| mk | 马其顿语 | 
| mg | 马尔加什语 | 
| ms | 马来文 | 
| mt | 马耳他文 | 
| mi | 毛利语 | 
| mr | 马拉地语 | 
| mn | 蒙古语 | 
| ne | 尼泊尔语 | 
| no | 挪威文 | 
| pl | 波兰文 | 
| pt | 葡萄牙文 | 
| ro | 罗马尼亚文 | 
| ru | 俄文 | 
| sm | 萨摩亚语 | 
| sr-Latn | 塞尔维亚文(拉丁文) | 
| sn | 修纳语 | 
| sk | 斯洛伐克文 | 
| sl | 斯洛文尼亚文 | 
| so | 索马里语 | 
| st | 塞索托语 | 
| es | 西班牙文 | 
| su | 印尼巽他语 | 
| sw | 斯瓦希里文 | 
| sv | 瑞典文 | 
| tl | 菲律宾语 | 
| tg | 塔吉克语 | 
| tr | 土耳其文 | 
| uk | 乌克兰文 | 
| uz | 乌兹别克语 | 
| vi | 越南文 | 
| cy | 威尔士文 | 
| fy | 弗里斯兰语 | 
| yo | 约鲁巴语 | 
| zu | 南非祖鲁语 | 
| hmn | 苗族语 | 
| xh | 班图 | 
| af | 南非荷兰 | 
| 支持图片格式 | 图片大小 | 每小时最大查询次数 | 
|---|---|---|
| jpg\png\bmp | 4M内(编码后) | 3600 | 
| 错误码 | 含义 | 
|---|---|
| 101 | 缺少必填的参数,首先确保必填参数齐全,然后,确认参数书写是否正确。 | 
| 102 | 不支持的语言类型 | 
| 103 | 翻译文本过长 | 
| 104 | 不支持的 API 类型 | 
| 105 | 不支持的签名类型 | 
| 106 | 不支持的响应类型 | 
| 107 | 不支持的传输加密类型 | 
| 108 | 应用 ID 无效,注册账号,登录后台创建应用和实例并完成绑定,可获得应用 ID 和应用密钥等信息 | 
| 109 | batchLog 格式不正确 | 
| 110 | 无相关服务的有效实例,应用没有绑定服务实例,可以新建服务实例,绑定服务实例。注:某些服务的结果发音需要 tts 实例,需要在控制台创建语音合成实例绑定应用后方能使用。 | 
| 111 | 开发者账号无效 | 
| 112 | 请求服务无效 | 
| 113 | img 不能为空 | 
| 114 | 不支持的图片传输方式 | 
| 201 | 解密失败,可能为 DES,BASE64,URLDecode 的错误 | 
| 202 | 签名检验失败,如果确认应用 ID 和应用密钥的正确性,仍返回 202,一般是编码问题。请确保翻译文本 q 为 UTF-8 编码. | 
| 203 | 访问 IP 地址不在可访问 IP 列表 | 
| 205 | 请求的接口与应用的平台类型不一致,,确保接入方式(Android SDK、IOS SDK、API)与创建的应用平台类型一致。如有疑问请参考入门指南 | 
| 206 | 因为时间戳无效导致签名校验失败 | 
| 207 | 重放请求 | 
| 301 | 辞典查询失败 | 
| 302 | 翻译查询失败 | 
| 303 | 服务端的其它异常 | 
| 304 | 会话闲置太久超时 | 
| 401 | 账户已经欠费停 | 
| 402 | offlinesdk 不可用 | 
| 411 | 访问频率受限,请稍后访问 | 
| 412 | 长请求过于频繁,请稍后访问 | 
| 1001 | 无效的 OCR 类型 | 
| 1002 | 不支持的 OCR image 类型 | 
| 1003 | 不支持的 OCR Language 类型 | 
| 1004 | 识别图片过大 | 
| 1201 | 图片 base64 解密失败 | 
| 1301 | OCR 段落识别失败 | 
| 1411 | 访问频率受限 | 
| 1412 | 超过最大识别字节数 | 
| 2003 | 不支持的语言识别 Language 类型 | 
| 2004 | 合成字符过长 | 
| 2005 | 不支持的音频文件类型 | 
| 2006 | 不支持的发音类型 | 
| 2201 | 解密失败 | 
| 2301 | 服务的异常 | 
| 2411 | 访问频率受限,请稍后访问 | 
| 2412 | 超过最大请求字符数 | 
| 3001 | 不支持的语音格式 | 
| 3002 | 不支持的语音采样率 | 
| 3003 | 不支持的语音声道 | 
| 3004 | 不支持的语音上传类型 | 
| 3005 | 不支持的语言类型 | 
| 3006 | 不支持的识别类型 | 
| 3007 | 识别音频文件过大 | 
| 3008 | 识别音频时长过长 | 
| 3009 | 不支持的音频文件类型 | 
| 3010 | 不支持的发音类型 | 
| 3201 | 解密失败 | 
| 3301 | 语音识别失败 | 
| 3302 | 语音翻译失败 | 
| 3303 | 服务的异常 | 
| 3411 | 访问频率受限,请稍后访问 | 
| 3412 | 超过最大请求字符数 | 
| 4001 | 不支持的语音识别格式 | 
| 4002 | 不支持的语音识别采样率 | 
| 4003 | 不支持的语音识别声道 | 
| 4004 | 不支持的语音上传类型 | 
| 4005 | 不支持的语言类型 | 
| 4006 | 识别音频文件过大 | 
| 4007 | 识别音频时长过长 | 
| 4201 | 解密失败 | 
| 4301 | 语音识别失败 | 
| 4303 | 服务的异常 | 
| 4411 | 访问频率受限,请稍后访问 | 
| 4412 | 超过最大请求时长 | 
| 5001 | 无效的 OCR 类型 | 
| 5002 | 不支持的 OCR image 类型 | 
| 5003 | 不支持的语言类型 | 
| 5004 | 识别图片过大 | 
| 5005 | 不支持的图片类型 | 
| 5006 | 文件为空 | 
| 5201 | 解密错误,图片 base64 解密失败 | 
| 5301 | OCR 段落识别失败 | 
| 5411 | 访问频率受限 | 
| 5412 | 超过最大识别流量 | 
| 9001 | 不支持的语音格式 | 
| 9002 | 不支持的语音采样率 | 
| 9003 | 不支持的语音声道 | 
| 9004 | 不支持的语音上传类型 | 
| 9005 | 不支持的语音识别 Language 类型 | 
| 9301 | ASR 识别失败 | 
| 9303 | 服务器内部错误 | 
| 9411 | 访问频率受限(超过最大调用次数) | 
| 9412 | 超过最大处理语音长度 | 
| 10001 | 无效的 OCR 类型 | 
| 10002 | 不支持的 OCR image 类型 | 
| 10004 | 识别图片过大 | 
| 10201 | 图片 base64 解密失败 | 
| 10301 | OCR 段落识别失败 | 
| 10411 | 访问频率受限 | 
| 10412 | 超过最大识别流量 | 
| 11001 | 不支持的语音识别格式 | 
| 11002 | 不支持的语音识别采样率 | 
| 11003 | 不支持的语音识别声道 | 
| 11004 | 不支持的语音上传类型 | 
| 11005 | 不支持的语言类型 | 
| 11006 | 识别音频文件过大 | 
| 11007 | 识别音频时长过长,最大支持 30s | 
| 11201 | 解密失败 | 
| 11301 | 语音识别失败 | 
| 11303 | 服务的异常 | 
| 11411 | 访问频率受限,请稍后访问 | 
| 11412 | 超过最大请求时长 | 
| 12001 | 图片尺寸过大 | 
| 12002 | 图片 base64 解密失败 | 
| 12003 | 引擎服务器返回错误 | 
| 12004 | 图片为空 | 
| 12005 | 不支持的识别图片类型 | 
| 12006 | 图片无匹配结果 | 
| 13001 | 不支持的角度类型 | 
| 13002 | 不支持的文件类型 | 
| 13003 | 表格识别图片过大 | 
| 13004 | 文件为空 | 
| 13301 | 表格识别失败 | 
| 15001 | 需要图片 | 
| 15002 | 图片过大(1M) | 
| 15003 | 服务调用失败 | 
| 17001 | 需要图片 | 
| 17002 | 图片过大(3M) | 
| 17003 | 识别类型未找到 | 
| 17004 | 不支持的识别类型 | 
| 17005 | 服务调用失败 | 
| 28102 | 不支持的 image 类型 | 
| 28104 | 识别图片过大, 图片大小上限 4M | 
| 28200 | 模版不存在, 请检查模版 Id 是否正确 | 
| 28201 | 模版未发布, 请在模版详情页面发布模版 | 
| 28202 | 模版已失效 | 
| 28203 | 模版用户不匹配 | 
| 28204 | 不支持的模板使用方式 | 
| 28205 | 模版创建失败 | 
| 28206 | 文字识别失败 | 
| 28207 | 不支持的generalOcr参数 | 
| 28208 | 模版Id不可为空 | 
| 28301 | 请求失败 | 
| 28302 | 文件过大 | 
| 28303 | 无此流水号 | 
| 28304 | 不支持的后缀名 | 
| 28400 | 字段格式名称已存在 | 
| 28401 | 字段格式操作失败 | 
| 28402 | 无此字段格式编号 | 
| 28403 | 字段格式编号重复 | 
| 28404 | 字段用户不匹配 | 
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class IOcrV3Demo {
    private static Logger logger = LoggerFactory.getLogger(OcrV3Demo.class);
    private static final String YOUDAO_URL = "https://openapi.youdao.com/iocr";
    private static final String APP_KEY = "您的应用ID";
    private static final String APP_SECRET = "您的应用密钥";
    public static void main(String[] args) throws IOException {
        Map<String,String> params = new HashMap<String,String>();
        String q = loadAsBase64("图片的路径");
        String salt = String.valueOf(System.currentTimeMillis());
        params.put("q", q);
        params.put("templateId", 模版Id);
        params.put("signType", "v3");
        String curtime = String.valueOf(System.currentTimeMillis() / 1000);
        params.put("curtime", curtime);
        String signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET;
        String sign = getDigest(signStr);
        params.put("appKey", APP_KEY);
        params.put("salt", salt);
        params.put("sign", sign);
        String result = requestForHttp(YOUDAO_URL,params);
        /** 处理结果 */
        System.out.println(result);
    }
    public static String requestForHttp(String url,Map<String,String> params) throws IOException {
        String result = "";
        /** 创建HttpClient */
        CloseableHttpClient httpClient = HttpClients.createDefault();
        /** httpPost */
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
        Iterator<Map.Entry<String,String>> it = params.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String,String> en = it.next();
            String key = en.getKey();
            String value = en.getValue();
            paramsList.add(new BasicNameValuePair(key,value));
        }
        httpPost.setEntity(new UrlEncodedFormEntity(paramsList,"UTF-8"));
        CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
        try{
            HttpEntity httpEntity = httpResponse.getEntity();
            result = EntityUtils.toString(httpEntity,"UTF-8");
            EntityUtils.consume(httpEntity);
        }finally {
            try{
                if(httpResponse!=null){
                    httpResponse.close();
                }
            }catch(IOException e){
                logger.info("## release resouce error ##" + e);
            }
        }
        return result;
    }
    /**
     * 生成加密字段
     */
    public static String getDigest(String string) {
        if (string == null) {
            return null;
        }
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        byte[] btInput = string.getBytes(StandardCharsets.UTF_8);
        try {
            MessageDigest mdInst = MessageDigest.getInstance("SHA-256");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }
    public static String loadAsBase64(String imgFile)
  {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
    File file = new File(imgFile);
    if(!file.exists()){
        logger.error("文件不存在");
        return null;
    }
    InputStream in = null;
    byte[] data = null;
      //读取图片字节数组
    try
    {
        in = new FileInputStream(imgFile);
        data = new byte[in.available()];
        in.read(data);
        in.close();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
      //对字节数组Base64编码
    return Base64.getEncoder().encodeToString(data);//返回Base64编码过的字节数组字符串
  }
  public static String truncate(String q) {
        if (q == null) {
            return null;
        }
        int len = q.length();
        String result;
        return len <= 20 ? q : (q.substring(0, 10) + len + q.substring(len - 10, len));
    }
}
# -*- coding: utf-8 -*-
import sys
import uuid
import requests
import base64
import hashlib
import time
reload(sys)
sys.setdefaultencoding('utf-8')
YOUDAO_URL = 'https://openapi.youdao.com/iocr'
APP_KEY = '您的应用ID'
APP_SECRET = '您的应用密钥'
def truncate(q):
    if q is None:
        return None
    q_utf8 = q.decode("utf-8")
    size = len(q_utf8)
    return q_utf8 if size <= 20 else q_utf8[0:10] + str(size) + q_utf8[size - 10:size]
def encrypt(signStr):
    hash_algorithm = hashlib.sha256()
    hash_algorithm.update(signStr.encode('utf-8'))
    return hash_algorithm.hexdigest()
def do_request(data):
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    return requests.post(YOUDAO_URL, data=data, headers=headers)
def connect():
    f = open(r'图片的路径', 'rb')  # 二进制方式打开图文件
    q = base64.b64encode(f.read())  # 读取文件内容,转换为base64编码
    f.close()
    data = {}
    data['q'] = q
    data['templateId'] = 模版id
    data['signType'] = 'v3'
    curtime = str(int(time.time()))
    data['curtime'] = curtime
    salt = str(uuid.uuid1())
    signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET
    sign = encrypt(signStr)
    data['appKey'] = APP_KEY
    data['salt'] = salt
    data['sign'] = sign
    response = do_request(data)
    print response.content
if __name__ == '__main__':
    connect()
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace zhiyun_csharp_demo
{
    class OcrV3Demo
    {
        public static void Main()
        {
            Dictionary dic = new Dictionary();
            string url = "https://openapi.youdao.com/iocr";
            string q = LoadAsBase64("图片的路径");
            string appKey = "您的应用ID";
            string appSecret = "您的应用密钥";
            string salt = DateTime.Now.Millisecond.ToString();
            dic.Add("templateId", 模版Id);
            dic.Add("signType", "v3");
            dic.Add("q", System.Web.HttpUtility.UrlEncode(q));
            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
            long millis = (long) ts.TotalMilliseconds;
            string curtime = Convert.ToString(millis / 1000);
            dic.Add("curtime", curtime);
            string signStr = appKey + Truncate(q) + salt + curtime + appSecret;;
            string sign = ComputeHash(signStr, new SHA256CryptoServiceProvider());
            dic.Add("appKey", appKey);
            dic.Add("salt", salt);
            dic.Add("sign", sign);
            string result = Post(url, dic);
            Console.WriteLine(result);
        }
        protected static string ComputeHash(string input, HashAlgorithm algorithm)
        {
          Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
          Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);
          return BitConverter.ToString(hashedBytes).Replace("-", "");
        }
        protected static string Truncate(string q)
        {
            if (q == null)
            {
               return null;
            }
            int len = q.Length;
            return len <= 20 ? q : (q.Substring(0, 10) + len + q.Substring(len - 10, 10));
        }
        protected static string LoadAsBase64(string filename)
        {
            try
            {
                FileStream filestream = new FileStream(filename, FileMode.Open);
                byte[] arr = new byte[filestream.Length];
                filestream.Position = 0;
                filestream.Read(arr, 0, (int)filestream.Length);
                filestream.Close();
                return Convert.ToBase64String(arr);
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        protected static string Post(string url, Dictionary dic)
        {
            string result = "";
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            StringBuilder builder = new StringBuilder();
            int i = 0;
            foreach (var item in dic)
            {
                if (i > 0)
                    builder.Append("&");
                builder.AppendFormat("{0}={1}", item.Key, item.Value);
                i++;
            }
            byte[] data = Encoding.UTF8.GetBytes(builder.ToString());
            req.ContentLength = data.Length;
            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }
            return result;
        }
    }
}
<?php
define("CURL_TIMEOUT",   2000);
define("URL",            "https://openapi.youdao.com/iocr");
define("APP_KEY",        "您的应用ID"); // 替换为您的应用ID
define("SEC_KEY",        "您的应用密钥"); // 替换为您的密钥
function do_request($q)
{
     $salt = create_guid();
     $args = array(
        'appKey' => APP_KEY,
        'salt' => $salt,
     );
     $args['q'] = $q;
     $args['templateId'] = 模版Id;
     $args['signType'] = 'v3';
     $curtime = strtotime("now");
     $args['curtime'] = $curtime;
     $signStr = APP_KEY . truncate($q) . $salt . $curtime . SEC_KEY;
     $args['sign'] = hash("sha256", $signStr);
     $ret = call(URL, $args);
     print_r($ret);
     $ret = json_decode($ret, true);
     return $ret;
}
// 发起网络请求
function call($url, $args=null, $method="post", $testflag = 0, $timeout = CURL_TIMEOUT, $headers=array())
{
    $ret = false;
    $i = 0;
    while($ret === false)
    {
        if($i > 1)
            break;
        if($i > 0)
        {
            sleep(1);
        }
         $ret = callOnce($url, $args, $method, false, $timeout, $headers);
         $i++;
    }
    return $ret;
}
function callOnce($url, $args=null, $method="post", $withCookie = false, $timeout = CURL_TIMEOUT, $headers=array())
{
    $ch = curl_init();
    if($method == "post")
    {
        $data = convert($args);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_POST, 1);
    }
    else
    {
        $data = convert($args);
        if($data)
        {
            if(stripos($url, "?") > 0)
            {
                 $url .= "&$data";
            }
            else
            {
                 $url .= "?$data";
            }
        }
    }
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    if(!empty($headers))
    {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    if($withCookie)
    {
        curl_setopt($ch, CURLOPT_COOKIEJAR, $_COOKIE);
    }
    $r = curl_exec($ch);
    curl_close($ch);
    return $r;
}
function convert(&$args)
{
    $data = '';
    if (is_array($args))
    {
        foreach ($args as $key=>$val)
        {
            if (is_array($val))
            {
                foreach ($val as $k=>$v)
                {
                     $data .= $key.'['.$k.']='.rawurlencode($v).'&';
                }
            }
            else
            {
                     $data .="$key=".rawurlencode($val)."&";
            }
        }
        return trim($data, "&");
    }
    return $args;
}
// uuid generator
function create_guid(){
    $microTime = microtime();
    list($a_dec, $a_sec) = explode(" ", $microTime);
    $dec_hex = dechex($a_dec* 1000000);
    $sec_hex = dechex($a_sec);
    ensure_length($dec_hex, 5);
    ensure_length($sec_hex, 6);
    $guid = "";
    $guid .= $dec_hex;
    $guid .= create_guid_section(3);
    $guid .= '-';
    $guid .= create_guid_section(4);
    $guid .= '-';
    $guid .= create_guid_section(4);
    $guid .= '-';
    $guid .= create_guid_section(4);
    $guid .= '-';
    $guid .= $sec_hex;
    $guid .= create_guid_section(6);
    return $guid;
}
function truncate($q) {
    $len = abslength($q);
    return $len <= 20 ? $q : (mb_substr($q, 0, 10) . $len . mb_substr($q, $len - 10, $len));
}
function abslength($str)
{
    if(empty($str)){
        return 0;
    }
    if(function_exists('mb_strlen')){
        return mb_strlen($str,'utf-8');
    }
    else {
        preg_match_all("/./u", $str, $ar);
        return count($ar[0]);
    }
}
function ensure_length(&$string, $length){
    $strlen = strlen($string);
    if($strlen < $length)
    {
         $string = str_pad($string, $length, "0");
    }
    else if($strlen > $length)
    {
         $string = substr($string, 0, $length);
    }
}
function create_guid_section($characters){
    $return = "";
    for($i = 0; $i < $characters; $i++)
    {
         $return .= dechex(mt_rand(0,15));
    }
    return $return;
}
// 输入
$file = "图片的路径";
$fp = fopen($file, "r") or die("Can't open file");
// base64编码
$q = base64_encode(fread($fp, filesize($file)));
fclose($fp);
do_request($q);
?>
| 日期 | 更新内容 | 
|---|---|
| 2020.04.10 | 更新接口返回值,测试接口地址 |