ALIYUN(阿里云)API 签名以及OCR调用
阿里云签名QT C++的实现
·
ALIYUN(阿里云)API 签名以及OCR调用
阿里云提供了部分免费的API使用次数,如OCR识别,机器翻译等。同时阿里云给出了一些代码的SDK供使用者调用这些API,本人主要使用的QT C++语言,无奈任何平台几乎都不会有完整的C++ SDK,最通用的调用就是通过平台的API接口。
阿里云的API接口不同于其他云平台的接口设计,其他云平台的接口只需要将内容拼接完成就可以直接GET或者POST,但是阿里云需要进行平台签名,将签名附带在请求中才可以,经过多次与阿里云工单沟通,先将完整的过程分享出来,供大家参考。
本案例包括阿里云的OCR与机器翻译操作过程
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMap>
#include <QByteArray>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_OCR_clicked();
QString in_urlEncode(QString strEncode);
QString in_ocrStrToSign(QString httpMethod);
QString computeHMACSHA1AndBase64(QByteArray key, QByteArray baseString);
void on_pushButton_trans_clicked();
private:
Ui::MainWindow *ui;
QMap<QString,QString> signMap; //用于关键字的 key value配对
QString ak_id = "your id";
QString ak_secret = "your secret";
};
#endif // MAINWINDOW_H
```cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QDebug>
#include <QFile>
#include <QUuid>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_OCR_clicked()
{
QLocale lo = QLocale::English;//设置QLocale为英文
//时间戳
QString timestamp = lo.toString(QDateTime::currentDateTimeUtc(),"yyyy-MM-ddTHH:mm:ssZ");
//生成随机数
QUuid id = QUuid::createUuid();
QString uuid = id.toString().remove("{").remove("}"); //获取UUid并去除左右括号
QString action = "RecognizeGeneral";
QString format = "JSON";
QString version = "2021-07-07";
QString http = "http://ocr-api.cn-hangzhou.aliyuncs.com/?";
// 按照阿里云的要求,将公共参数组装起来,如果识别的是在线图片如:Url=http://mycat.dg.png // 这个URl我随便写的,也需要将url这个公共参数,插入signMap进行前面个signMap.insert("Url","http://mycat.dg.png "); 注意HTTP方式徐采用GET方式
//ocr ****************************
signMap.insert("AccessKeyId",ak_id);
signMap.insert("Action",action);
signMap.insert("Format",format);
signMap.insert("Timestamp",timestamp);
signMap.insert("SignatureNonce",uuid);
signMap.insert("Version",version);
signMap.insert("SignatureMethod","HMAC-SHA1");
signMap.insert("SignatureVersion","1.0");
//ocr*****************************
// 由于识别本地图片,所以采用POST
//in_ocrStrToSign 这个函数用来签名
QString postString = in_ocrStrToSign("POST&%2F&");
QNetworkAccessManager *aliyun_Manager = new QNetworkAccessManager();//后需要连接以下槽函数
QNetworkRequest req;
req.setRawHeader("Content-Type", "application/octet-stream");
//设置url
req.setUrl(http+postString);
//发送请求
QFile *file = new QFile();
file->setFileName("D:/Desktop/OCR/trans.PNG");
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << "Failed to open the file:" << file->errorString();
} else {
// Send the POST request with the file as the request body
QNetworkReply* reply =aliyun_Manager->post(req, file);
QEventLoop eventLoop;
connect(aliyun_Manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec();
do
{
QApplication::processEvents(QEventLoop::AllEvents, 10);
}while(!reply->isFinished());
if(reply->isFinished())
{
QByteArray responseData;
responseData = reply->readAll();
qDebug()<<responseData;
}
}
}
QString MainWindow::in_urlEncode(QString strEncode)
{
// 按照阿里云签名机制,排除不需要编码的字符,指定不需要编码的字符列表
QString safeCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
// 使用QUrl::toPercentEncoding对字符串进行编码
QByteArray encodedData = QUrl::toPercentEncoding(strEncode, safeCharacters.toUtf8());
QString encodedString = QString::fromUtf8(encodedData);
return encodedString;
}
QString MainWindow::in_ocrStrToSign(QString httpMethod)
{
QString stringToSign;
for (auto it = signMap.constBegin(); it != signMap.constEnd(); ++it)
{
//将signMpa里面的数据拼接起来,同时对value值进行URLENCODE编码
stringToSign += it.key() + "=" + in_urlEncode(it.value()) + "&";
}
// 去掉最后一个'&'
if (!stringToSign.isEmpty()) {
stringToSign.chop(1);
}
// 把拼接好的url再次转码
stringToSign = in_urlEncode(stringToSign);
// url转码后拼接method方式
stringToSign =httpMethod+stringToSign;
// 获得签名
QString signature = computeHMACSHA1AndBase64(QString(ak_secret+"&").toLocal8Bit(),stringToSign.toLocal8Bit());
// 签名URL编码
signature = in_urlEncode(signature);
signMap.insert("Signature",signature);
QString httpString;
// 把签名拼接到请求的字符串中 注意这里不需要编码了
for (auto it = signMap.constBegin(); it != signMap.constEnd(); ++it)
{
httpString += it.key() + "=" + it.value() + "&";
}
// 去掉最后一个'&'
if (! httpString.isEmpty()) {
httpString.chop(1);
}
return httpString;
}
QString MainWindow::computeHMACSHA1AndBase64(QByteArray key, QByteArray baseString)
{
int blockSize = 64; // HMAC-SHA-1 block size, defined in SHA-1 standard
if (key.length() > blockSize) { // if key is longer than block size (64), reduce key length with SHA-1 compression
key = QCryptographicHash::hash(key, QCryptographicHash::Sha1);
}
QByteArray innerPadding(blockSize, char(0x36)); // initialize inner padding with char"6"
QByteArray outerPadding(blockSize, char(0x5c)); // initialize outer padding with char"/"
// ascii characters 0x36 ("6") and 0x5c ("/") are selected because they have large
// Hamming distance (http://en.wikipedia.org/wiki/Hamming_distance)
for (int i = 0; i < key.length(); i++) {
innerPadding[i] = innerPadding[i] ^ key.at(i); // XOR operation between every byte in key and innerpadding, of key length
outerPadding[i] = outerPadding[i] ^ key.at(i); // XOR operation between every byte in key and outerpadding, of key length
}
// result = hash ( outerPadding CONCAT hash ( innerPadding CONCAT baseString ) ).toBase64
QByteArray total = outerPadding;
QByteArray part = innerPadding;
part.append(baseString);
total.append(QCryptographicHash::hash(part, QCryptographicHash::Sha1));
QByteArray hashed = QCryptographicHash::hash(total, QCryptographicHash::Sha1);
return hashed.toBase64();
}
void MainWindow::on_pushButton_trans_clicked()
{
//本部分为机器翻译API,过程和OCR一致,唯一的区别在于需要将请求字符串中的所有参数都需要进行URL编码,具体看signmap里面的内容
QLocale lo = QLocale::English;//设置QLocale为英文
QString timestamp = lo.toString(QDateTime::currentDateTimeUtc(),"yyyy-MM-ddTHH:mm:ssZ");
//生成随机数
QUuid id = QUuid::createUuid();
QString uuid = id.toString().remove("{").remove("}"); //获取UUid并去除左右括号
QString action = "RecognizeGeneral";
QString version = "2021-07-07";
QString format = "JSON";
QString http = "http://ocr-api.cn-hangzhou.aliyuncs.com/?";
//trans ***********************
QString FormatType = "text";
version = "2018-10-12";
action = "TranslateGeneral";
http =" http://mt.cn-hangzhou.aliyuncs.com/?";
signMap.insert("AccessKeyId",ak_id);
signMap.insert("Action",action);
signMap.insert("Timestamp",timestamp);
signMap.insert("SignatureNonce",uuid);
signMap.insert("Version",version);
signMap.insert("SignatureMethod","HMAC-SHA1");
signMap.insert("SignatureVersion","1.0");
signMap.insert("FormatType",FormatType);
signMap.insert("Scene","general");
signMap.insert("SourceLanguage","zh");
signMap.insert("SourceText","你好");
signMap.insert("TargetLanguage","en");
signMap.insert("Format",format);
QString postString = in_ocrStrToSign("GET&%2F&");
QString httpstr = "http://mt.cn-hangzhou.aliyuncs.com/?Action=TranslateGeneral&FormatType=text"
"&Scene=general&SourceLanguage=zh&SourceText=你好&TargetLanguage=en&"+postString;
qDebug()<<httpstr;
QNetworkAccessManager *aliyun_Manager = new QNetworkAccessManager();//后需要连接以下槽函数
QNetworkRequest req;
// //设置url
req.setUrl(httpstr);
QNetworkReply* reply =aliyun_Manager->get(req);
QEventLoop eventLoop;
connect(aliyun_Manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec();
do
{
QApplication::processEvents(QEventLoop::AllEvents, 10);
}while(!reply->isFinished());
if(reply->isFinished())
{
QByteArray responseData;
responseData = reply->readAll();
qDebug()<<responseData;
}
}
更多推荐
所有评论(0)