Compare commits

...

3 Commits

Author SHA1 Message Date
zhuzichu 6a925bdad3 update network 2023-11-29 18:10:56 +08:00
zhuzichu 6999067a80 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-11-29 10:42:09 +08:00
zhuzichu 1047fac4d6 update 2023-11-29 10:41:48 +08:00
5 changed files with 318 additions and 22 deletions

View File

@ -2,8 +2,8 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Dialogs
import FluentUI
import Qt.labs.platform
import "qrc:///example/qml/component"
FluContentPage{
@ -348,6 +348,32 @@ FluContentPage{
file_dialog.open()
}
}
FluProgressButton{
id:btn_download
implicitWidth: parent.width
implicitHeight: 36
text: "Download File"
onClicked: {
folder_dialog.showDialog(function(path){
FluNetwork.get("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
.toDownload(path)
.go(callable_download_file)
})
}
}
FluProgressButton{
id:btn_download_breakpoint
implicitWidth: parent.width
implicitHeight: 36
text: "Breakpoint Download File"
onClicked: {
folder_dialog.showDialog(function(path){
FluNetwork.get("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
.toDownload(path,true)
.go(callable_breakpoint_download_file)
})
}
}
}
}
@ -375,6 +401,56 @@ FluContentPage{
}
}
FluNetworkCallable{
id:callable_download_file
onStart: {
btn_download.progress = 0
btn_download.disabled = true
}
onFinish: {
btn_download.disabled = false
}
onError:
(status,errorString,result)=>{
btn_download.progress = 0
showError(errorString)
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
showSuccess(result)
}
onDownloadProgress:
(recv,total)=>{
btn_download.progress = recv/total
}
}
FluNetworkCallable{
id:callable_breakpoint_download_file
onStart: {
btn_download_breakpoint.progress = 0
btn_download_breakpoint.disabled = true
}
onFinish: {
btn_download_breakpoint.disabled = false
}
onError:
(status,errorString,result)=>{
btn_download_breakpoint.progress = 0
showError(errorString)
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
showSuccess(result)
}
onDownloadProgress:
(recv,total)=>{
btn_download_breakpoint.progress = recv/total
}
}
FileDialog {
id: file_dialog
onAccepted: {
@ -386,6 +462,20 @@ FluContentPage{
}
}
FileDialog {
property var onSelectListener
id: folder_dialog
currentFile: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]+"/big_buck_bunny.mp4"
fileMode: FileDialog.SaveFile
onAccepted: {
folder_dialog.onSelectListener(FluTools.toLocalPath(folder_dialog.currentFile))
}
function showDialog(listener){
folder_dialog.onSelectListener = listener
folder_dialog.open()
}
}
FluArea{
anchors{
top: layout_flick.top

View File

@ -41,6 +41,9 @@ Item {
}
Component.onCompleted: {
FluNetwork.setInterceptor(function(param){
param.addHeader("Token","000000000000000000000")
})
FluApp.init(app)
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
FluApp.vsync = SettingsHelper.getVsync()

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import Qt.labs.platform 1.0
import "qrc:///example/qml/component"
import "../component"
@ -339,6 +340,95 @@ FluContentPage{
.go(callable)
}
}
FluProgressButton{
id:btn_upload
implicitWidth: parent.width
implicitHeight: 36
text: "Upload File"
onClicked: {
file_dialog.open()
}
}
FluProgressButton{
id:btn_download
implicitWidth: parent.width
implicitHeight: 36
text: "Download File"
onClicked: {
folder_dialog.open()
}
}
}
}
FluNetworkCallable{
id:callable_upload_file
onStart: {
btn_upload.disabled = true
}
onFinish: {
btn_upload.disabled = false
}
onError:
(status,errorString,result)=>{
btn_upload.progress = 0
text_info.text = result
console.debug(result)
}
onSuccess:
(result)=>{
text_info.text = result
}
onUploadProgress:
(sent,total)=>{
btn_upload.progress = sent/total
}
}
FluNetworkCallable{
id:callable_download_file
onStart: {
btn_download.progress = 0
btn_download.disabled = true
}
onFinish: {
btn_download.disabled = false
}
onError:
(status,errorString,result)=>{
btn_download.progress = 0
showError(errorString)
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
showSuccess(result)
}
onDownloadProgress:
(recv,total)=>{
btn_download.progress = recv/total
}
}
FileDialog {
id: file_dialog
onAccepted: {
FluNetwork.postForm("https://httpbingo.org/post")
.setRetry(0)//
.add("accessToken","12345678")
.addFile("file",FluTools.toLocalPath(file_dialog.selectedFile))
.go(callable_upload_file)
}
}
FileDialog {
id: folder_dialog
currentFile: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]+"/big_buck_bunny.mp4"
fileMode: FileDialog.SaveFile
onAccepted: {
FluNetwork.get("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
.toDownload(FluTools.toLocalPath(folder_dialog.currentFile))
.go(callable_download_file)
}
}

View File

@ -7,6 +7,9 @@
#include <QNetworkReply>
#include <QJsonObject>
#include <QNetworkDiskCache>
#include <QQmlEngine>
#include <QQmlContext>
#include <QJSEngine>
#include <QJsonArray>
#include <QStandardPaths>
#include <QDir>
@ -127,11 +130,22 @@ QString NetworkParams::buildCacheKey(){
obj.insert("param",QString(QJsonDocument::fromVariant(_paramMap).toJson(QJsonDocument::Compact)));
obj.insert("header",QString(QJsonDocument::fromVariant(_headerMap).toJson(QJsonDocument::Compact)));
obj.insert("file",QString(QJsonDocument::fromVariant(_fileMap).toJson(QJsonDocument::Compact)));
if(_downloadParam){
QJsonObject downObj;
QString _destPath;
bool _append;
downObj.insert("destPath",_downloadParam->_destPath);
downObj.insert("append",_downloadParam->_append);
obj.insert("download",downObj);
}
QByteArray data = QJsonDocument(obj).toJson(QJsonDocument::Compact);
return QCryptographicHash::hash(data, QCryptographicHash::Sha256).toHex();
}
void NetworkParams::go(NetworkCallable* callable){
QJSValueList data;
data<<qjsEngine(FluNetwork::getInstance())->newQObject(this);
FluNetwork::getInstance()->_interceptor.call(data);
if(_downloadParam){
FluNetwork::getInstance()->handleDownload(this,callable);
}else{
@ -140,11 +154,11 @@ void NetworkParams::go(NetworkCallable* callable){
}
void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
QString cacheKey = params->buildCacheKey();
QPointer<NetworkCallable> callable(c);
if(!callable.isNull()){
callable->start();
}
QString cacheKey = params->buildCacheKey();
if(params->_cacheMode == FluNetworkType::CacheMode::FirstCacheThenRequest && cacheExists(cacheKey)){
if(!callable.isNull()){
callable->cache(readCache(cacheKey));
@ -202,8 +216,99 @@ void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
sendRequest(manager,request,params,reply,callable);
}
void FluNetwork::handleDownload(NetworkParams* params,NetworkCallable* result){
void FluNetwork::handleDownload(NetworkParams* params,NetworkCallable* c){
QString cacheKey = params->buildCacheKey();
QPointer<NetworkCallable> callable(c);
if(!callable.isNull()){
callable->start();
}
QUrl url(params->_url);
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkReply *reply = nullptr;
manager->setTransferTimeout(params->getTimeout());
addQueryParam(&url,params->_queryMap);
QNetworkRequest request(url);
addHeaders(&request,params->_headerMap);
QString cachePath = getCacheFilePath(cacheKey);
QString destPath = params->_downloadParam->_destPath;
QFile* destFile = new QFile(destPath);
QFile* cacheFile = new QFile(cachePath);
bool isOpen = false;
qint64 seek = 0;
if(cacheFile->exists() && destFile->exists() && params->_downloadParam->_append){
QJsonObject cacheInfo = QJsonDocument::fromJson(readCache(cacheKey).toUtf8()).object();
qint64 fileSize = cacheInfo.value("fileSize").toDouble();
qint64 contentLength = cacheInfo.value("contentLength").toDouble();
if(fileSize == contentLength && destFile->size() == contentLength){
if(!callable.isNull()){
callable->downloadProgress(fileSize,contentLength);
callable->success(destPath);
callable->finish();
}
return;
}
if(fileSize==destFile->size()){
request.setRawHeader("Range", QString("bytes=%1-").arg(fileSize).toUtf8());
seek = fileSize;
isOpen = destFile->open(QIODevice::WriteOnly|QIODevice::Append);
}else{
isOpen = destFile->open(QIODevice::WriteOnly|QIODevice::Truncate);
}
}else{
isOpen = destFile->open(QIODevice::WriteOnly|QIODevice::Truncate);
}
if(!isOpen){
if(!callable.isNull()){
callable->error(-1,"device not open","");
callable->finish();
}
return;
}
if(params->_downloadParam->_append){
if (!cacheFile->open(QIODevice::WriteOnly|QIODevice::Truncate))
{
if(!callable.isNull()){
callable->error(-1,"cache file device not open","");
callable->finish();
}
return;
}
}
reply = manager->get(request);
destFile->setParent(reply);
cacheFile->setParent(reply);
connect(reply,&QNetworkReply::readyRead,reply,[reply,seek,destFile,cacheFile,callable]{
if (!reply || !destFile || reply->error() != QNetworkReply::NoError)
{
return;
}
QMap<QString, QVariant> downInfo;
qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong()+seek;
downInfo.insert("contentLength",contentLength);
QString eTag = reply->header(QNetworkRequest::ETagHeader).toString();
downInfo.insert("eTag",eTag);
destFile->write(reply->readAll());
destFile->flush();
downInfo.insert("fileSize",destFile->size());
if(cacheFile->isOpen()){
cacheFile->resize(0);
cacheFile->write(QJsonDocument::fromVariant(QVariant(downInfo)).toJson().toBase64());
cacheFile->flush();
}
if(!callable.isNull()){
callable->downloadProgress(destFile->size(),contentLength);
}
});
connect(manager,&QNetworkAccessManager::finished,this,[params,manager,callable](QNetworkReply *reply){
params->deleteLater();
reply->deleteLater();
manager->deleteLater();
if(!callable.isNull()){
callable->finish();
}
});
}
QString FluNetwork::readCache(const QString& key){
@ -346,73 +451,77 @@ FluNetwork::FluNetwork(QObject *parent): QObject{parent}
}
NetworkParams* FluNetwork::get(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_GET);
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_GET,this);
}
NetworkParams* FluNetwork::head(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_HEAD);
return new NetworkParams(url,NetworkParams::TYPE_NONE,NetworkParams::METHOD_HEAD,this);
}
NetworkParams* FluNetwork::postBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_POST);
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_POST,this);
}
NetworkParams* FluNetwork::putBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PUT);
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PUT,this);
}
NetworkParams* FluNetwork::patchBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PATCH);
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_PATCH,this);
}
NetworkParams* FluNetwork::deleteBody(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_DELETE);
return new NetworkParams(url,NetworkParams::TYPE_BODY,NetworkParams::METHOD_DELETE,this);
}
NetworkParams* FluNetwork::postForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_POST);
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_POST,this);
}
NetworkParams* FluNetwork::putForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PUT);
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PUT,this);
}
NetworkParams* FluNetwork::patchForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PATCH);
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_PATCH,this);
}
NetworkParams* FluNetwork::deleteForm(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_DELETE);
return new NetworkParams(url,NetworkParams::TYPE_FORM,NetworkParams::METHOD_DELETE,this);
}
NetworkParams* FluNetwork::postJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_POST);
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_POST,this);
}
NetworkParams* FluNetwork::putJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PUT);
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PUT,this);
}
NetworkParams* FluNetwork::patchJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PATCH);
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_PATCH,this);
}
NetworkParams* FluNetwork::deleteJson(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_DELETE);
return new NetworkParams(url,NetworkParams::TYPE_JSON,NetworkParams::METHOD_DELETE,this);
}
NetworkParams* FluNetwork::postJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_POST);
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_POST,this);
}
NetworkParams* FluNetwork::putJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PUT);
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PUT,this);
}
NetworkParams* FluNetwork::patchJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PATCH);
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_PATCH,this);
}
NetworkParams* FluNetwork::deleteJsonArray(const QString& url){
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_DELETE);
return new NetworkParams(url,NetworkParams::TYPE_JSONARRAY,NetworkParams::METHOD_DELETE,this);
}
void FluNetwork::setInterceptor(QJSValue interceptor){
this->_interceptor = interceptor;
}

View File

@ -5,6 +5,7 @@
#include <QtQml/qqml.h>
#include <QFile>
#include <QJsonValue>
#include <QJSValue>
#include <QNetworkAccessManager>
#include "Def.h"
#include "stdafx.h"
@ -64,7 +65,7 @@ public:
Q_INVOKABLE NetworkParams* setTimeout(int val);
Q_INVOKABLE NetworkParams* setRetry(int val);
Q_INVOKABLE NetworkParams* setCacheMode(int val);
Q_INVOKABLE NetworkParams* toDownload(QString destPath,bool append);
Q_INVOKABLE NetworkParams* toDownload(QString destPath,bool append = false);
Q_INVOKABLE void go(NetworkCallable* result);
QString buildCacheKey();
QString method2String();
@ -116,6 +117,7 @@ public:
Q_INVOKABLE NetworkParams* putJsonArray(const QString& url);
Q_INVOKABLE NetworkParams* patchJsonArray(const QString& url);
Q_INVOKABLE NetworkParams* deleteJsonArray(const QString& url);
Q_INVOKABLE void setInterceptor(QJSValue interceptor);
void handle(NetworkParams* params,NetworkCallable* result);
void handleDownload(NetworkParams* params,NetworkCallable* result);
private:
@ -126,6 +128,8 @@ private:
QString readCache(const QString& key);
bool cacheExists(const QString& key);
QString getCacheFilePath(const QString& key);
public:
QJSValue _interceptor;
};
#endif // FLUNETWORK_H