使用Qt备份微信小程序腾讯云数据库到本地(databaseMigrateExport和databaseMigrateQueryInfo)

小程序云开发提供了方便的云数据库供我们直接使用,但是在程序升级和后台数据管理过程中,可能会出现因为误操作等意外,导致一些不可避免数据库中数据的安全,比如不小心删除了数据集合,写入了脏数据等。

云数据库中的数据我们可以使用小程序开发者工具中的控制台进行操作,但必须要安装有开发者工具且操作用户微信被授权登录才可以进行管理维护。因此我使用Qt制作PC端应用程序,通过HTTP API调用的方式管理维护后台数据,这里介绍对云数据库中集合进行备份到本地的功能实现。

通过查阅微信的文档,可以发现云开发提供了数据导出接口databaseMigrateExport

请求地址

POST https://api.weixin.qq.com/tcb/databasemigrateexport?access_token=ACCESS_TOKEN

# 请求参数

属性类型默认值必填说明
access_tokenstring 接口调用凭证
envstring 云环境ID
file_pathstring 导出文件路径(文件会导出到同环境的云存储中,可使用获取下载链接 API 获取下载链接)
file_typenumber 导出文件类型,文件格式参考数据库导入指引中的文件格式部分
querystring 导出条件

需要说明的是,此处导出的环境文档中写着同环境云存储中,但是并不是小程序云开发中,因此在导出的备份文件是不能在云开发控制台中的存储里找到的,因此参数中的file_path可以随意写,不需要根据云存储中文件夹路径来。

第一步:获取access_token

获取access_token的方法我之前博客有介绍,此处不过多阐述。传送门:Qt 连接管理微信小程序云数据库一(获取微信后台接口调用凭据ACCESS_TOKEN)

第二步:获取导出任务ID:job_id

获取 access_token 后,就可以使用 databaseMigrateExport 接口导出数据进行备份,该API接口返回导出任务ID,使用该任务ID,使用databaseMigrateQueryInfo接口,就可以查看到服务端中数据备份导出的状态。

void JsonDataModel::initial(){
    manager = new QNetworkAccessManager(this);
    request = new QNetworkRequest();
    request->setHeader(QNetworkRequest::ContentTypeHeader,"application/json; encoding=utf-8");
}
request->setUrl(QUrl(tr("https://api.weixin.qq.com/tcb/databasemigrateexport?access_token=%1").arg(Access_Token)));
    QString path = ".json";
    QString query = tr("db.collection('record').get()");
    QJsonObject obj{
        {"file_path","record.json"},
        {"env",env},
        {"file_type",1},//1:json格式;2:csv格式
        {"query",query}
    };
    QByteArray oby = QJsonDocument(obj).toJson();
    QNetworkReply* r = manager->post(*request,oby);
    QEventLoop loop;
    connect(r, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();//开启事件循环,等待接收到响应数据
    QByteArray ba = r->readAll();
    QJsonDocument callbackJson = QJsonDocument::fromJson(ba);
    job_id = callbackJson["job_id"];
    qDebug()<<callbackJson;//打印返回的数据内容
    r->deleteLater();

返回结果为:

QJsonDocument({"errcode":0,"errmsg":"ok","job_id":100692781}) 

第三步:查询任务状态,获取文件下载地址

使用databaseMigrateQueryInfo接口查询当前任务ID的状态,接口文档:

请求地址

POST https://api.weixin.qq.com/tcb/databasemigratequeryinfo?access_token=ACCESS_TOKEN

# 请求参数

属性类型默认值必填说明
access_tokenstring 接口调用凭证
envstring 云环境ID
job_idnumber 迁移任务ID

通过测试发现数据库的数据导出并不是同步的,而是需要一定时间的,数据量越大导出所要花费的时间就越多。接口返回的数据中status代表了备份数据导出的状态,因此我使用QTimer设计一个计时器,每隔200ms发送一次状态请求,当发现导出成功时,停止计时器,下载备份文件。

    QTimer *timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(checkBackup()));
    timer->start(200);
void JsonDataModel::checkBackup(){
    QTimer* timer = qobject_cast<QTimer*>(sender());
    request->setUrl(QUrl(tr("https://api.weixin.qq.com/tcb/databasemigratequeryinfo?access_token=%1").arg(Access_Token)));
    QJsonObject obj{
        {"env",env},
        {"job_id",job_id}
    };
    QByteArray objBy= QJsonDocument(obj).toJson();
    QNetworkReply* r = manager->post(*request,objBy);
    QEventLoop loop;
    connect(r, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();
    QByteArray ba = r->readAll();
    QJsonDocument js_r = QJsonDocument::fromJson(ba);
    qDebug()<<js_r;//打印返回数据内容
    QString file_url = js_r["file_url"].toString();
    if(file_url!=""){
        timer->stop();//当返回下载地址不为空时,停止计时器
    }
}

 打印输出:

QJsonDocument({"errcode":0,"errmsg":"ok","error_msg":"","file_url":"","record_fail":0,"record_success":0,"status":"waiting"})

QJsonDocument({"errcode":0,"errmsg":"ok","error_msg":"","file_url":"","record_fail":0,"record_success":0,"status":"migrating"}))

QJsonDocument({"errcode":0,"errmsg":"ok","error_msg":"导出完成.","file_url":"https://tcb-mongodb-data-1254135806.cos.ap-shanghai.myqcloud.com/100013993337/record.json?q-sign-algorithm=sha1&q-ak=AKIDsp8NUoE8C8yd9TvEemXUh9Wy&q-sign-time=1592803039;1592806639&q-key-time=1592803039;1592806639&r-list=&q-url-param-list=&q-signature=06763f74cee1b3577d17f9ef82dae1a23add","record_fail":0,"record_success":10,"status":"success"})

此处的file_url就是备份文件的下载地址

第四步:下载备份文件至本地磁盘

    if(file_url!=""){
        timer->stop();
        QString path = QDir::currentPath()+"/record.json";
        QFile file(path);
        request->setUrl(QUrl(file_url));
        QNetworkReply* rr = manager->get(*request);
        connect(rr, SIGNAL(finished()), &loop, SLOT(quit()));
        loop.exec();
        QByteArray ba_file = rr->readAll();
        file.open(QIODevice::WriteOnly);
        file.write(ba_file);
        file.close();
    }

备份数据如下:

当需要还原数据时使用云开发控制台导入数据即可

完整代码:

void JsonDataModel::initial(){
    manager = new QNetworkAccessManager(this);
    request = new QNetworkRequest();
    request->setHeader(QNetworkRequest::ContentTypeHeader,"application/json; encoding=utf-8");
}

void JsonDataModel::backupDataBase(){
    request->setUrl(QUrl(tr("https://api.weixin.qq.com/tcb/databasemigrateexport?access_token=%1").arg(Access_Token)));
    QString path = ".json";
    QString query = tr("db.collection('record').get()");
    QJsonObject obj{
        {"file_path","record.json"},
        {"env",env},
        {"file_type",1},
        {"query",query}
    };
    QByteArray oby = QJsonDocument(obj).toJson();
    QNetworkReply* r = manager->post(*request,oby);
    QEventLoop loop;
    connect(r, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();
    QByteArray ba = r->readAll();
    QJsonDocument callbackJson = QJsonDocument::fromJson(ba);
    job_id = callbackJson["job_id"];
    qDebug()<<callbackJson;
    QTimer *timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(checkBackup()));
    timer->start(200);
    r->deleteLater();
}

void JsonDataModel::checkBackup(){
    QTimer* timer = qobject_cast<QTimer*>(sender());
    request->setUrl(QUrl(tr("https://api.weixin.qq.com/tcb/databasemigratequeryinfo?access_token=%1").arg(Access_Token)));
    QJsonObject obj{
        {"env",env},
        {"job_id",job_id}
    };
    QByteArray objBy= QJsonDocument(obj).toJson();
    QNetworkReply* r = manager->post(*request,objBy);
    QEventLoop loop;
    connect(r, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();
    QByteArray ba = r->readAll();
    QJsonDocument js_r = QJsonDocument::fromJson(ba);
    qDebug()<<js_r;
    QString file_url = js_r["file_url"].toString();
    if(file_url!=""){
        timer->stop();
        QString path = QDir::currentPath()+"/record.json";
        QFile file(path);
        request->setUrl(QUrl(file_url));
        QNetworkReply* rr = manager->get(*request);
        connect(rr, SIGNAL(finished()), &loop, SLOT(quit()));
        loop.exec();
        QByteArray ba_file = rr->readAll();
        file.open(QIODevice::WriteOnly);
        file.write(ba_file);
        file.close();
        rr->deleteLater();
        timer->deleteLater();
        r->deleteLater();
    }
}

如果搭配上databaseCollectionGet的获取云数据库所有集合信息,加上循环,就可以自动将数据库中所有集合备份到本地:

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喵喵叫的猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值