remove FluHttp

This commit is contained in:
朱子楚\zhuzi 2023-11-29 21:35:06 +08:00
parent 6a925bdad3
commit 394d0ab244
23 changed files with 136 additions and 1696 deletions

View File

@ -143,7 +143,6 @@
<file>qml/page/T_Expander.qml</file>
<file>qml/page/T_FlipView.qml</file>
<file>qml/page/T_Home.qml</file>
<file>qml/page/T_Http.qml</file>
<file>qml/page/T_Image.qml</file>
<file>qml/page/T_InfoBar.qml</file>
<file>qml/page/T_Menu.qml</file>

View File

@ -24,23 +24,10 @@ Item {
}
}
FluHttpInterceptor{
id:interceptor
function onIntercept(request){
if(request.method === "get"){
request.params["method"] = "get"
}
if(request.method === "post"){
request.params["method"] = "post"
}
request.headers["token"] ="yyds"
request.headers["os"] ="pc"
console.debug(JSON.stringify(request))
return request
}
}
Component.onCompleted: {
FluNetwork.setInterceptor(function(param){
param.addHeader("Token","000000000000000000000")
})
FluApp.init(app)
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
FluApp.vsync = SettingsHelper.getVsync()
@ -57,7 +44,6 @@ Item {
"/pageWindow":"qrc:/example/qml/window/PageWindow.qml"
}
FluApp.initialRoute = "/"
FluApp.httpInterceptor = interceptor
FluApp.run()
}
}

View File

@ -130,7 +130,6 @@ FluExpander{
"FluRadioButtons",
"FluImage",
"FluSpinBox",
"FluHttp",
"FluWatermark",
"FluTour",
"FluQRCode",
@ -140,7 +139,8 @@ FluExpander{
"FluStaggeredView",
"FluProgressButton",
"FluLoadingButton",
"FluClip"
"FluClip",
"FluNetwork"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");

View File

@ -406,12 +406,6 @@ FluObject{
url:"qrc:/example/qml/page/T_Chart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"Http(Deprecated)"
menuDelegate: paneItemMenu
url:"qrc:/example/qml/page/T_Http.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"Network"
menuDelegate: paneItemMenu

View File

@ -1,405 +0,0 @@
import QtQuick
import Qt.labs.platform
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Dialogs
import FluentUI
import "qrc:///example/qml/component"
FluContentPage{
title:"Http"
property string cacheDirPath: StandardPaths.writableLocation(StandardPaths.AppLocalDataLocation) + "/cache/http"
property bool isDownCompleted: false
FluHttp{
id:http
cacheDir:cacheDirPath
}
FluHttp{
id:http_breakpoint_download
cacheDir:cacheDirPath
breakPointDownload: true
}
FluHttp{
id:http_cache_ifnonecacherequest
cacheMode:FluHttpType.IfNoneCacheRequest
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_requestfailedreadcache
cacheMode:FluHttpType.RequestFailedReadCache
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_firstcachethenrequest
cacheMode:FluHttpType.FirstCacheThenRequest
cacheDir:cacheDirPath
}
HttpCallable{
id:callable
onStart: {
showLoading()
}
onFinish: {
hideLoading()
}
onError:
(status,errorString,result)=>{
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
text_info.text = result
}
onCache:
(result)=>{
text_info.text = result
}
}
Flickable{
id:layout_flick
width: 200
clip: true
anchors{
top: parent.top
topMargin: 20
bottom: parent.bottom
left: parent.left
}
ScrollBar.vertical: FluScrollBar {}
contentHeight:layout_column.height
Column{
spacing: 2
id:layout_column
width: parent.width
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Get请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/get")
http.get(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post表单请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
var params = {}
params.custname = "朱子楚"
params.custtel = "1234567890"
params.custemail = "zhuzichu520@gmail.com"
request.params = params
var headers = {}
headers.test = "123456789456465321354"
request.headers = headers
http.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post Json请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
var params = {}
params.custname = "朱子楚"
params.custtel = "1234567890"
params.custemail = "zhuzichu520@gmail.com"
request.params = params
http.postJson(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post String请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = "我命由我不由天"
http.postString(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Delete请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/delete")
http.deleteResource(request,callable)
}
}
FluProgressButton{
id:btn_download
implicitWidth: parent.width
implicitHeight: 36
text: "下载文件"
onClicked: {
folder_dialog.open()
}
}
FluProgressButton{
property bool downloading: false
id:btn_breakpoint_download
implicitWidth: parent.width
implicitHeight: 36
text: {
if(downloading){
return "暂停下载"
}
if(progress === 0){
return "断点下载文件"
}else if(progress === 1){
return "打开文件"
}else{
return "继续下载"
}
}
HttpRequest{
id:request_breakpoint_download
url: "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
downloadSavePath: FluTools.getApplicationDirPath()+ "/download/big_buck_bunny.mp4"
}
HttpCallable{
id:callable_breakpoint_download
onStart: {
btn_breakpoint_download.downloading = true
}
onFinish: {
btn_breakpoint_download.downloading = false
}
onError:
(status,errorString,result)=>{
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
if(!isDownCompleted){
tour.open()
isDownCompleted = true
}
showSuccess(result)
}
onDownloadProgress:
(recv,total)=>{
btn_breakpoint_download.progress = recv/total
}
}
Component.onCompleted: {
progress = http_breakpoint_download.getBreakPointProgress(request_breakpoint_download)
}
onClicked: {
if(downloading){
http_breakpoint_download.cancel()
return
}
if(progress === 1){
FluTools.showFileInFolder(request_breakpoint_download.downloadSavePath)
}else{
http_breakpoint_download.download(request_breakpoint_download,callable_breakpoint_download)
}
}
FluMenu{
id:menu_breakpoint_download
width: 120
FluMenuItem{
text: "删除文件"
onClicked: {
if(FluTools.removeFile(request_breakpoint_download.downloadSavePath)){
btn_breakpoint_download.progress = 0
}
}
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
if(btn_breakpoint_download.progress === 1){
menu_breakpoint_download.popup()
}
}
}
}
FluProgressButton{
id:btn_upload
implicitWidth: parent.width
implicitHeight: 36
text: "文件上传"
onClicked: {
file_dialog.open()
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "FirstCacheThenRequest缓存"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = {cacheMode:"FirstCacheThenRequest"}
http_cache_firstcachethenrequest.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "RequestFailedReadCache缓存"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = {cacheMode:"RequestFailedReadCache"}
http_cache_requestfailedreadcache.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "IfNoneCacheRequest缓存"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = {cacheMode:"IfNoneCacheRequest"}
http_cache_ifnonecacherequest.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "打开缓存路径"
onClicked: {
Qt.openUrlExternally(cacheDirPath)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "删除缓存"
onClicked: {
console.debug(FluTools.removeDir(cacheDirPath))
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "清空右边数据"
onClicked: {
text_info.text = ""
}
}
}
}
FluTour{
id:tour
steps:[
{title:"友情提示",description: "下载已完成,左击这里可以打开文件所在路径,右击可以弹出菜单删除文件!",target:()=>btn_breakpoint_download}
]
}
HttpCallable{
id:callable_upload
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
}
}
FileDialog {
id: file_dialog
onAccepted: {
var request = http.newRequest("https://httpbingo.org/post")
var params = {}
for(var i=0;i<selectedFiles.length;i++){
var fileUrl = selectedFiles[i]
var fileName = FluTools.getFileNameByUrl(fileUrl)
var filePath = FluTools.toLocalPath(fileUrl)
params[fileName] = filePath
}
request.params = params
http.upload(request,callable_upload)
}
}
HttpCallable{
id:callable_download
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
}
}
FolderDialog {
id: folder_dialog
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
onAccepted: {
var request = http.newRequest("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
request.downloadSavePath = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4"
http.download(request,callable_download)
}
}
FluArea{
anchors{
top: layout_flick.top
bottom: layout_flick.bottom
left: layout_flick.right
right: parent.right
leftMargin: 8
}
Flickable{
clip: true
id:scrollview
boundsBehavior:Flickable.StopAtBounds
width: parent.width
height: parent.height
contentWidth: width
contentHeight: text_info.height
ScrollBar.vertical: FluScrollBar {}
FluText{
id:text_info
width: scrollview.width
wrapMode: Text.WrapAnywhere
padding: 14
}
}
}
}

View File

@ -8,6 +8,7 @@ import "qrc:///example/qml/component"
FluContentPage{
id:root
title:"Network"
FluNetworkCallable{
@ -59,6 +60,7 @@ FluContentPage{
.addQuery("name","孙悟空")
.addQuery("age",500)
.addQuery("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -70,6 +72,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.postBody("https://httpbingo.org/post")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -83,6 +86,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -96,6 +100,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -109,6 +114,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -120,6 +126,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.putBody("https://httpbingo.org/put")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -133,6 +140,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -146,6 +154,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -159,6 +168,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -170,6 +180,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.patchBody("https://httpbingo.org/patch")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -183,6 +194,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -196,6 +208,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -209,6 +222,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -220,6 +234,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.deleteBody("https://httpbingo.org/delete")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -233,6 +248,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -246,6 +262,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -259,6 +276,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -274,6 +292,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -289,6 +308,7 @@ FluContentPage{
.add("age",500)
.add("address","花果山水帘洞")
.add("cacheMode","RequestFailedReadCache")
.bind(root)
.go(callable)
}
}
@ -304,6 +324,7 @@ FluContentPage{
.add("age",500)
.add("address","花果山水帘洞")
.add("cacheMode","IfNoneCacheRequest")
.bind(root)
.go(callable)
}
}
@ -319,6 +340,7 @@ FluContentPage{
.add("age",500)
.add("address","花果山水帘洞")
.add("cacheMode","FirstCacheThenRequest")
.bind(root)
.go(callable)
}
}
@ -336,6 +358,7 @@ FluContentPage{
.add("address","花果山水帘洞")
.add("timeout","5000")
.add("retry","3")
.bind(root)
.go(callable)
}
}
@ -357,6 +380,7 @@ FluContentPage{
folder_dialog.showDialog(function(path){
FluNetwork.get("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
.toDownload(path)
.bind(root)
.go(callable_download_file)
})
}
@ -370,6 +394,7 @@ FluContentPage{
folder_dialog.showDialog(function(path){
FluNetwork.get("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
.toDownload(path,true)
.bind(root)
.go(callable_breakpoint_download_file)
})
}
@ -458,6 +483,7 @@ FluContentPage{
.setRetry(0)//
.add("accessToken","12345678")
.addFile("file",FluTools.toLocalPath(file_dialog.selectedFile))
.bind(root)
.go(callable_upload_file)
}
}
@ -465,6 +491,7 @@ FluContentPage{
FileDialog {
property var onSelectListener
id: folder_dialog
folder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
currentFile: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]+"/big_buck_bunny.mp4"
fileMode: FileDialog.SaveFile
onAccepted: {

View File

@ -164,7 +164,7 @@ FluWindow {
id:loader
lazy: true
anchors.fill: parent
source: "https://zhu-zichu.gitee.io/Qt6_156_LieflatPage.qml"
source: "https://zhu-zichu.gitee.io/Qt_163_LieflatPage.qml"
}
}
front: Item{
@ -294,10 +294,6 @@ FluWindow {
}
}
FluHttp{
id:http
}
FpsItem{
id:fps_item
}
@ -327,7 +323,7 @@ FluWindow {
}
}
HttpCallable{
FluNetworkCallable{
id:callable
property bool silent: true
onStart: {
@ -363,8 +359,8 @@ FluWindow {
function checkUpdate(silent){
callable.silent = silent
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
http.get(request,callable);
FluNetwork.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
.go(callable)
}
}

View File

@ -24,22 +24,6 @@ Item {
}
}
FluHttpInterceptor{
id:interceptor
function onIntercept(request){
if(request.method === "get"){
request.params["method"] = "get"
}
if(request.method === "post"){
request.params["method"] = "post"
}
request.headers["token"] ="yyds"
request.headers["os"] ="pc"
console.debug(JSON.stringify(request))
return request
}
}
Component.onCompleted: {
FluNetwork.setInterceptor(function(param){
param.addHeader("Token","000000000000000000000")
@ -60,7 +44,6 @@ Item {
"/pageWindow":"qrc:/example/qml/window/PageWindow.qml"
}
FluApp.initialRoute = "/"
FluApp.httpInterceptor = interceptor
FluApp.run()
}
}

View File

@ -130,7 +130,6 @@ FluExpander{
"FluRadioButtons",
"FluImage",
"FluSpinBox",
"FluHttp",
"FluWatermark",
"FluTour",
"FluQRCode",
@ -140,7 +139,8 @@ FluExpander{
"FluStaggeredView",
"FluProgressButton",
"FluLoadingButton",
"FluClip"
"FluClip",
"FluNetwork"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");

View File

@ -406,12 +406,6 @@ FluObject{
url:"qrc:/example/qml/page/T_Chart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"Http(Deprecated)"
menuDelegate: paneItemMenu
url:"qrc:/example/qml/page/T_Http.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:"Network"
menuDelegate: paneItemMenu

View File

@ -1,406 +0,0 @@
import QtQuick 2.15
import Qt.labs.platform 1.1
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Dialogs 1.3
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluContentPage{
title:"Http"
property string cacheDirPath: StandardPaths.writableLocation(StandardPaths.AppLocalDataLocation) + "/cache/http"
property bool isDownCompleted: false
FluHttp{
id:http
cacheDir:cacheDirPath
}
FluHttp{
id:http_breakpoint_download
cacheDir:cacheDirPath
breakPointDownload: true
}
FluHttp{
id:http_cache_ifnonecacherequest
cacheMode:FluHttpType.IfNoneCacheRequest
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_requestfailedreadcache
cacheMode:FluHttpType.RequestFailedReadCache
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_firstcachethenrequest
cacheMode:FluHttpType.FirstCacheThenRequest
cacheDir:cacheDirPath
}
HttpCallable{
id:callable
onStart: {
showLoading()
}
onFinish: {
hideLoading()
}
onError:
(status,errorString,result)=>{
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
text_info.text = result
}
onCache:
(result)=>{
text_info.text = result
}
}
Flickable{
id:layout_flick
width: 200
clip: true
anchors{
top: parent.top
topMargin: 20
bottom: parent.bottom
left: parent.left
}
ScrollBar.vertical: FluScrollBar {}
contentHeight:layout_column.height
Column{
spacing: 2
id:layout_column
width: parent.width
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Get请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/get")
http.get(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post表单请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
var params = {}
params.custname = "朱子楚"
params.custtel = "1234567890"
params.custemail = "zhuzichu520@gmail.com"
request.params = params
var headers = {}
headers.test = "123456789456465321354"
request.headers = headers
http.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post Json请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
var params = {}
params.custname = "朱子楚"
params.custtel = "1234567890"
params.custemail = "zhuzichu520@gmail.com"
request.params = params
http.postJson(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Post String请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = "我命由我不由天"
http.postString(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Delete请求"
onClicked: {
var request = http.newRequest("https://httpbingo.org/delete")
http.deleteResource(request,callable)
}
}
FluProgressButton{
id:btn_download
implicitWidth: parent.width
implicitHeight: 36
text: "下载文件"
onClicked: {
folder_dialog.open()
}
}
FluProgressButton{
property bool downloading: false
id:btn_breakpoint_download
implicitWidth: parent.width
implicitHeight: 36
text: {
if(downloading){
return "暂停下载"
}
if(progress === 0){
return "断点下载文件"
}else if(progress === 1){
return "打开文件"
}else{
return "继续下载"
}
}
HttpRequest{
id:request_breakpoint_download
url: "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
downloadSavePath: FluTools.getApplicationDirPath()+ "/download/big_buck_bunny.mp4"
}
HttpCallable{
id:callable_breakpoint_download
onStart: {
btn_breakpoint_download.downloading = true
}
onFinish: {
btn_breakpoint_download.downloading = false
}
onError:
(status,errorString,result)=>{
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
if(!isDownCompleted){
tour.open()
isDownCompleted = true
}
showSuccess(result)
}
onDownloadProgress:
(recv,total)=>{
btn_breakpoint_download.progress = recv/total
}
}
Component.onCompleted: {
progress = http_breakpoint_download.getBreakPointProgress(request_breakpoint_download)
}
onClicked: {
if(downloading){
http_breakpoint_download.cancel()
return
}
if(progress === 1){
FluTools.showFileInFolder(request_breakpoint_download.downloadSavePath)
}else{
http_breakpoint_download.download(request_breakpoint_download,callable_breakpoint_download)
}
}
FluMenu{
id:menu_breakpoint_download
width: 120
FluMenuItem{
text: "删除文件"
onClicked: {
if(FluTools.removeFile(request_breakpoint_download.downloadSavePath)){
btn_breakpoint_download.progress = 0
}
}
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
if(btn_breakpoint_download.progress === 1){
menu_breakpoint_download.popup()
}
}
}
}
FluProgressButton{
id:btn_upload
implicitWidth: parent.width
implicitHeight: 36
text: "文件上传"
onClicked: {
file_dialog.open()
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "FirstCacheThenRequest缓存"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = {cacheMode:"FirstCacheThenRequest"}
http_cache_firstcachethenrequest.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "RequestFailedReadCache缓存"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = {cacheMode:"RequestFailedReadCache"}
http_cache_requestfailedreadcache.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "IfNoneCacheRequest缓存"
onClicked: {
var request = http.newRequest("https://httpbingo.org/post")
request.params = {cacheMode:"IfNoneCacheRequest"}
http_cache_ifnonecacherequest.post(request,callable)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "打开缓存路径"
onClicked: {
Qt.openUrlExternally(cacheDirPath)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "删除缓存"
onClicked: {
console.debug(FluTools.removeDir(cacheDirPath))
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "清空右边数据"
onClicked: {
text_info.text = ""
}
}
}
}
FluTour{
id:tour
steps:[
{title:"友情提示",description: "下载已完成,左击这里可以打开文件所在路径,右击可以弹出菜单删除文件!",target:()=>btn_breakpoint_download}
]
}
HttpCallable{
id:callable_upload
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
}
}
FileDialog {
id: file_dialog
onAccepted: {
var request = http.newRequest("https://httpbingo.org/post")
var params = {}
for(var i=0;i<selectedFiles.length;i++){
var fileUrl = selectedFiles[i]
var fileName = FluTools.getFileNameByUrl(fileUrl)
var filePath = FluTools.toLocalPath(fileUrl)
params[fileName] = filePath
}
request.params = params
http.upload(request,callable_upload)
}
}
HttpCallable{
id:callable_download
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
}
}
FolderDialog {
id: folder_dialog
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
onAccepted: {
var request = http.newRequest("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
request.downloadSavePath = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4"
http.download(request,callable_download)
}
}
FluArea{
anchors{
top: layout_flick.top
bottom: layout_flick.bottom
left: layout_flick.right
right: parent.right
leftMargin: 8
}
Flickable{
clip: true
id:scrollview
boundsBehavior:Flickable.StopAtBounds
width: parent.width
height: parent.height
contentWidth: width
contentHeight: text_info.height
ScrollBar.vertical: FluScrollBar {}
FluText{
id:text_info
width: scrollview.width
wrapMode: Text.WrapAnywhere
padding: 14
}
}
}
}

View File

@ -9,6 +9,7 @@ import "../component"
FluContentPage{
id:root
title:"Network"
FluNetworkCallable{
@ -60,6 +61,7 @@ FluContentPage{
.addQuery("name","孙悟空")
.addQuery("age",500)
.addQuery("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -71,6 +73,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.postBody("https://httpbingo.org/post")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -84,6 +87,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -97,6 +101,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -110,6 +115,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -121,6 +127,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.putBody("https://httpbingo.org/put")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -134,6 +141,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -147,6 +155,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -160,6 +169,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -171,6 +181,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.patchBody("https://httpbingo.org/patch")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -184,6 +195,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -197,6 +209,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -210,6 +223,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -221,6 +235,7 @@ FluContentPage{
text_info.text = ""
FluNetwork.deleteBody("https://httpbingo.org/delete")
.setBody("花果山水帘洞美猴王齐天大圣孙悟空")
.bind(root)
.go(callable)
}
}
@ -234,6 +249,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -247,6 +263,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -260,6 +277,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -275,6 +293,7 @@ FluContentPage{
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
@ -290,6 +309,7 @@ FluContentPage{
.add("age",500)
.add("address","花果山水帘洞")
.add("cacheMode","RequestFailedReadCache")
.bind(root)
.go(callable)
}
}
@ -305,6 +325,7 @@ FluContentPage{
.add("age",500)
.add("address","花果山水帘洞")
.add("cacheMode","IfNoneCacheRequest")
.bind(root)
.go(callable)
}
}
@ -320,6 +341,7 @@ FluContentPage{
.add("age",500)
.add("address","花果山水帘洞")
.add("cacheMode","FirstCacheThenRequest")
.bind(root)
.go(callable)
}
}
@ -337,6 +359,7 @@ FluContentPage{
.add("address","花果山水帘洞")
.add("timeout","5000")
.add("retry","3")
.bind(root)
.go(callable)
}
}
@ -355,7 +378,26 @@ FluContentPage{
implicitHeight: 36
text: "Download File"
onClicked: {
folder_dialog.open()
folder_dialog.showDialog(function(path){
FluNetwork.get("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
.toDownload(path)
.bind(root)
.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)
.bind(root)
.go(callable_breakpoint_download_file)
})
}
}
}
@ -410,6 +452,31 @@ FluContentPage{
}
}
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: {
@ -417,18 +484,23 @@ FluContentPage{
.setRetry(0)//
.add("accessToken","12345678")
.addFile("file",FluTools.toLocalPath(file_dialog.selectedFile))
.bind(root)
.go(callable_upload_file)
}
}
FileDialog {
property var onSelectListener
id: folder_dialog
folder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
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)
folder_dialog.onSelectListener(FluTools.toLocalPath(folder_dialog.currentFile))
}
function showDialog(listener){
folder_dialog.onSelectListener = listener
folder_dialog.open()
}
}

View File

@ -167,7 +167,7 @@ FluWindow {
id:loader
lazy: true
anchors.fill: parent
source: "https://zhu-zichu.gitee.io/Qt5_156_LieflatPage.qml"
source: "https://zhu-zichu.gitee.io/Qt_163_LieflatPage.qml"
}
}
front: Item{
@ -297,10 +297,6 @@ FluWindow {
}
}
FluHttp{
id:http
}
FpsItem{
id:fps_item
}
@ -330,7 +326,7 @@ FluWindow {
}
}
HttpCallable{
FluNetworkCallable{
id:callable
property bool silent: true
onStart: {
@ -366,8 +362,8 @@ FluWindow {
function checkUpdate(silent){
callable.silent = silent
var request = http.newRequest("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
http.get(request,callable);
FluNetwork.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
.go(callable)
}
}

View File

@ -14,18 +14,6 @@ Q_ENUM_NS(Scope)
QML_NAMED_ELEMENT(FluViewModelType)
}
namespace FluHttpType {
Q_NAMESPACE
enum CacheMode {
NoCache = 0x0000,
RequestFailedReadCache = 0x0001,
IfNoneCacheRequest = 0x0002,
FirstCacheThenRequest = 0x0004,
};
Q_ENUM_NS(CacheMode)
QML_NAMED_ELEMENT(FluHttpType)
}
namespace FluNetworkType {
Q_NAMESPACE
enum CacheMode {

View File

@ -16,7 +16,6 @@ FRAMELESSHELPER_USE_NAMESPACE
FluApp::FluApp(QObject *parent):QObject{parent}{
connect(this,&FluApp::useSystemAppBarChanged,this,[=]{FramelessConfig::instance()->set(Global::Option::UseSystemAppBar,_useSystemAppBar);});
vsync(true);
httpInterceptor(nullptr);
useSystemAppBar(false);
}

View File

@ -9,7 +9,6 @@
#include <QJsonObject>
#include <QQmlEngine>
#include "FluRegister.h"
#include "FluHttpInterceptor.h"
#include "stdafx.h"
#include "singleton.h"
@ -22,7 +21,6 @@ class FluApp : public QObject
Q_PROPERTY_AUTO(bool,vsync)
Q_PROPERTY_AUTO(QString,initialRoute);
Q_PROPERTY_AUTO(QJsonObject,routes);
Q_PROPERTY_AUTO(FluHttpInterceptor*,httpInterceptor);
Q_PROPERTY_AUTO(bool,useSystemAppBar);
QML_NAMED_ELEMENT(FluApp)
QML_SINGLETON

View File

@ -1,681 +0,0 @@
#include "FluHttp.h"
#include <QThreadPool>
#include <QEventLoop>
#include <QNetworkReply>
#include <QUrlQuery>
#include <QHttpMultiPart>
#include <QGuiApplication>
#include <QJsonDocument>
#include <QStandardPaths>
#include <QTextStream>
#include <QDir>
#include "Def.h"
#include "FluApp.h"
#include "FluTools.h"
HttpRequest::HttpRequest(QObject *parent):QObject{parent}{
}
QMap<QString, QVariant> HttpRequest::toMap(){
QVariant _params;
bool isPostString = method() == "postString";
if(params().isNull()){
if(isPostString){
_params = "";
}else{
_params = QMap<QString,QVariant>();
}
}else{
_params = params();
}
QVariant _headers;
if(headers().isNull()){
_headers = QMap<QString,QVariant>();
}else{
_headers = headers();
}
QMap<QString, QVariant> request = {
{"url",url()},
{"headers",_headers.toMap()},
{"method",method()},
{"downloadSavePath",downloadSavePath()}
};
if(isPostString){
request.insert("params",_params.toString());
}else{
request.insert("params",_params.toMap());
}
return request;
}
QString HttpRequest::httpId(){
return FluTools::getInstance()->sha256(QJsonDocument::fromVariant(QVariant(toMap())).toJson(QJsonDocument::Compact));
}
HttpCallable::HttpCallable(QObject *parent):QObject{parent}{
}
FluHttp::FluHttp(QObject *parent):QObject{parent}{
retry(3);
timeout(15000);
cacheMode(FluHttpType::CacheMode::NoCache);
cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+"/httpcache");
breakPointDownload(false);
}
FluHttp::~FluHttp(){
cancel();
}
void FluHttp::cancel(){
foreach (QPointer<QNetworkReply> item, _cacheReply) {
if(item){
item->abort();
}
}
}
void FluHttp::post(HttpRequest* r,HttpCallable* c){
auto request = QPointer(r);
auto callable = QPointer(c);
request->method("post");
auto requestMap = request->toMap();
auto httpId = request->httpId();
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
onFinish(callable,request);
return;
}
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
QNetworkAccessManager manager;
manager.setTransferTimeout(timeout());
for (int i = 0; i < retry(); ++i) {
QUrl url(request->url());
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QHttpMultiPart multiPart(QHttpMultiPart::FormDataType);
for (const auto& each : data["params"].toMap().toStdMap())
{
const QString& key = each.first;
const QString& value = each.second.toString();
QString dispositionHeader = QString("form-data; name=\"%1\"").arg(key);
QHttpPart part;
part.setHeader(QNetworkRequest::ContentDispositionHeader, dispositionHeader);
part.setBody(value.toUtf8());
multiPart.append(part);
}
QNetworkReply* reply = manager.post(req,&multiPart);
if(!QPointer(qApp)){
reply->deleteLater();
reply = nullptr;
return;
}
_cacheReply.append(reply);
QEventLoop loop;
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
loop.exec();
QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
handleCache(httpId,result);
onSuccess(callable,result);
break;
}else{
if(i == retry()-1){
if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
onError(callable,status,errorString,result);
}
}
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});
}
void FluHttp::postString(HttpRequest* r,HttpCallable* c){
auto request = QPointer(r);
auto callable = QPointer(c);
request->method("postString");
auto requestMap = request->toMap();
auto httpId = request->httpId();
QString params = request->params().toString();
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
onFinish(callable,request);
return;
}
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
QNetworkAccessManager manager;
manager.setTransferTimeout(timeout());
for (int i = 0; i < retry(); ++i) {
QUrl url(request->url());
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QString contentType = QString("text/plain;charset=utf-8");
req.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
QNetworkReply* reply = manager.post(req,params.toUtf8());
if(!QPointer(qApp)){
reply->deleteLater();
reply = nullptr;
return;
}
_cacheReply.append(reply);
QEventLoop loop;
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
loop.exec();
QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
handleCache(httpId,result);
onSuccess(callable,result);
break;
}else{
if(i == retry()-1){
if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
onError(callable,status,errorString,result);
}
}
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});
}
void FluHttp::postJson(HttpRequest* r,HttpCallable* c){
auto request = QPointer(r);
auto callable = QPointer(c);
request->method("postJson");
auto requestMap = request->toMap();
auto httpId = request->httpId();
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
onFinish(callable,request);
return;
}
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
QNetworkAccessManager manager;
manager.setTransferTimeout(timeout());
for (int i = 0; i < retry(); ++i) {
QUrl url(request->url());
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QString contentType = QString("application/json;charset=utf-8");
req.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
QNetworkReply* reply = manager.post(req,QJsonDocument::fromVariant(data["params"]).toJson());
if(!QPointer(qApp)){
reply->deleteLater();
reply = nullptr;
return;
}
_cacheReply.append(reply);
QEventLoop loop;
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
loop.exec();
QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
handleCache(httpId,result);
onSuccess(callable,result);
break;
}else{
if(i == retry()-1){
if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
onError(callable,status,errorString,result);
}
}
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});
}
void FluHttp::get(HttpRequest* r,HttpCallable* c){
auto request = QPointer(r);
auto callable = QPointer(c);
request->method("get");
auto requestMap = request->toMap();
auto httpId = request->httpId();
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
onFinish(callable,request);
return;
}
QNetworkAccessManager manager;
manager.setTransferTimeout(timeout());
for (int i = 0; i < retry(); ++i) {
QUrl url(request->url());
addQueryParam(&url,data["params"].toMap());
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QNetworkReply* reply = manager.get(req);
if(!QPointer(qApp)){
reply->deleteLater();
reply = nullptr;
return;
}
_cacheReply.append(reply);
QEventLoop loop;
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
loop.exec();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
QString result = QString::fromUtf8(reply->readAll());
if (isSuccess) {
handleCache(httpId,result);
onSuccess(callable,result);
break;
}else{
if(i == retry()-1){
if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
onError(callable,status,errorString,result);
}
}
reply->deleteLater();
reply = nullptr;
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});
}
void FluHttp::download(HttpRequest* r,HttpCallable* c){
auto request = QPointer(r);
auto callable = QPointer(c);
request->method("download");
auto requestMap = request->toMap();
auto httpId = request->httpId();
auto savePath = request->downloadSavePath();
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
QNetworkAccessManager manager;
QUrl url(request->url());
addQueryParam(&url,data["params"].toMap());
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QSharedPointer<QFile> file(new QFile(savePath));
QDir dir = QFileInfo(savePath).path();
if (!dir.exists(dir.path())){
dir.mkpath(dir.path());
}
qint64 seek = 0;
auto filePath = getCacheFilePath(httpId);
QSharedPointer<QFile> fileCache(new QFile(filePath));
if(fileCache->exists() && file->exists() && _breakPointDownload){
QJsonObject cacheInfo = QJsonDocument::fromJson(readCache(httpId).toUtf8()).object();
qint64 fileSize = cacheInfo.value("fileSize").toDouble();
qint64 contentLength = cacheInfo.value("contentLength").toDouble();
if(fileSize == contentLength && file->size() == contentLength){
onDownloadProgress(callable,fileSize,contentLength);
onSuccess(callable,savePath);
onFinish(callable,request);
return;
}
if(fileSize==file->size()){
req.setRawHeader("Range", QString("bytes=%1-").arg(fileSize).toUtf8());
seek = fileSize;
file->open(QIODevice::WriteOnly|QIODevice::Append);
}else{
file->open(QIODevice::WriteOnly|QIODevice::Truncate);
}
}else{
file->open(QIODevice::WriteOnly|QIODevice::Truncate);
}
QNetworkReply* reply = manager.get(req);
if(!QPointer(qApp)){
reply->deleteLater();
reply = nullptr;
return;
}
_cacheReply.append(reply);
QEventLoop loop;
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
if (!fileCache->open(QIODevice::WriteOnly|QIODevice::Truncate))
{
qDebug()<<"FileCache Error";
}
connect(reply,&QNetworkReply::readyRead,reply,[reply,file,fileCache,requestMap,callable,seek,this]{
if (!reply || !file || reply->error() != QNetworkReply::NoError)
{
return;
}
QMap<QString, QVariant> downMap = requestMap;
qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong()+seek;
downMap.insert("contentLength",contentLength);
QString eTag = reply->header(QNetworkRequest::ETagHeader).toString();
downMap.insert("eTag",eTag);
file->write(reply->readAll());
file->flush();
downMap.insert("fileSize",file->size());
fileCache->resize(0);
fileCache->write(FluTools::getInstance()->toBase64(QJsonDocument::fromVariant(QVariant(downMap)).toJson()).toUtf8());
fileCache->flush();
onDownloadProgress(callable,file->size(),contentLength);
});
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
onSuccess(callable,savePath);
}else{
onError(callable,reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),reply->errorString(),"");
}
reply->deleteLater();
reply = nullptr;
onFinish(callable,request);
});
}
void FluHttp::upload(HttpRequest* request,HttpCallable* callable){
request->method("upload");
auto requestMap = request->toMap();
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
QNetworkAccessManager manager;
manager.setTransferTimeout(timeout());
QUrl url(request->url());
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QHttpMultiPart multiPart(QHttpMultiPart::FormDataType);
for (const auto& each : data["params"].toMap().toStdMap())
{
const QString& key = each.first;
const QString& filePath = each.second.toString();
QFile *file = new QFile(filePath);
file->open(QIODevice::ReadOnly);
file->setParent(&multiPart);
QString dispositionHeader = QString("form-data; name=\"%1\"; filename=\"%2\"").arg(key,filePath);
QHttpPart part;
part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
part.setHeader(QNetworkRequest::ContentDispositionHeader, dispositionHeader);
part.setBodyDevice(file);
multiPart.append(part);
}
QNetworkReply* reply = manager.post(req,&multiPart);
if(!QPointer(qApp)){
reply->deleteLater();
reply = nullptr;
return;
}
_cacheReply.append(reply);
QEventLoop loop;
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop,reply](){reply->abort(),loop.quit();});
connect(reply,&QNetworkReply::uploadProgress,reply,[=](qint64 bytesSent, qint64 bytesTotal){
onUploadProgress(callable,bytesSent,bytesTotal);
});
loop.exec();
QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError;
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
onSuccess(callable,result);
}else{
onError(callable,status,errorString,result);
}
onFinish(callable,request);
});
}
void FluHttp::deleteResource(HttpRequest* request,HttpCallable* callable)
{
request->method("deleteResource");
auto requestMap = request->toMap();
auto httpId = request->httpId();
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(httpId)){
onCache(callable,readCache(httpId));
onFinish(callable,request);
return;
}
QNetworkAccessManager manager;
manager.setTransferTimeout(timeout());
for (int i = 0; i < retry(); ++i) {
QUrl url(request->url());
addQueryParam(&url,data["params"].toMap());
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QEventLoop loop;
QNetworkReply* reply = manager.deleteResource(req);
_cacheReply.append(reply);
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();});
loop.exec();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError;
QString result = QString::fromUtf8(reply->readAll());
if (isSuccess) {
handleCache(httpId,result);
onSuccess(callable,result);
break;
}else{
if(i == retry()-1){
if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache && cacheExists(httpId)){
onCache(callable,readCache(httpId));
}
onError(callable,status,errorString,result);
}
}
QNetworkReply::NetworkError error = reply->error();
if(error == QNetworkReply::OperationCanceledError){
break;
}
reply->deleteLater();
reply = nullptr;
}
onFinish(callable,request);
});
}
QVariant FluHttp::invokeIntercept(QMap<QString, QVariant> request){
if(!FluApp::getInstance()->httpInterceptor()){
return request;
}
QVariant target;
QMetaObject::invokeMethod(FluApp::getInstance()->httpInterceptor(), "onIntercept",Q_RETURN_ARG(QVariant,target),Q_ARG(QVariant, request));
return target;
}
void FluHttp::addQueryParam(QUrl* url,const QMap<QString, QVariant>& params){
QMapIterator<QString, QVariant> iter(params);
QUrlQuery urlQuery(*url);
while (iter.hasNext())
{
iter.next();
urlQuery.addQueryItem(iter.key(), iter.value().toString());
}
url->setQuery(urlQuery);
}
void FluHttp::addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers){
QMapIterator<QString, QVariant> iter(headers);
while (iter.hasNext())
{
iter.next();
request->setRawHeader(iter.key().toUtf8(), iter.value().toString().toUtf8());
}
}
QString FluHttp::readCache(const QString& httpId){
auto filePath = getCacheFilePath(httpId);
QString result;
QFile file(filePath);
if(!file.exists()){
return result;
}
if (file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file);
result = FluTools::getInstance()->fromBase64(stream.readAll().toUtf8());
}
return result;
}
bool FluHttp::cacheExists(const QString& httpId){
return QFile(getCacheFilePath(httpId)).exists();
}
QString FluHttp::getCacheFilePath(const QString& httpId){
QString path = FluTools::getInstance()->toLocalPath(QUrl(_cacheDir));
QDir dir = path;
if (!dir.exists(path)){
dir.mkpath(path);
}
auto filePath = path+"/"+httpId;
return filePath;
}
void FluHttp::handleCache(const QString& httpId,const QString& result){
if(_cacheMode==FluHttpType::CacheMode::NoCache){
return;
}
auto filePath = getCacheFilePath(httpId);
QSharedPointer<QFile> file(new QFile(filePath));
QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate;
if (!file->open(mode))
{
return;
}
file->write(FluTools::getInstance()->toBase64(result).toUtf8());
}
qreal FluHttp::getBreakPointProgress(HttpRequest* request){
request->method("download");
auto httpId = request->httpId();
QSharedPointer<QFile> file(new QFile(request->downloadSavePath()));
auto filePath = getCacheFilePath(httpId);
QSharedPointer<QFile> fileCache(new QFile(filePath));
if(fileCache->exists() && file->exists() && _breakPointDownload){
QJsonObject cacheInfo = QJsonDocument::fromJson(readCache(httpId).toUtf8()).object();
double fileSize = cacheInfo.value("fileSize").toDouble();
double contentLength = cacheInfo.value("contentLength").toDouble();
if(fileSize == contentLength && file->size() == contentLength){
return 1;
}
if(fileSize==file->size()){
return fileSize/contentLength;
}else{
return 0;
}
}else{
return 0;
}
}
HttpRequest* FluHttp::newRequest(QString url){
HttpRequest* request = new HttpRequest(this);
request->url(url);
return request;
}
void FluHttp::onStart(QPointer<HttpCallable> callable){
if (!callable.isNull()) {
Q_EMIT callable->start();
}
}
void FluHttp::onFinish(QPointer<HttpCallable> callable,QPointer<HttpRequest> request){
if (!callable.isNull()) {
Q_EMIT callable->finish();
}
if(request&&request->parent()->inherits("FluHttp")){
request->deleteLater();
}
}
void FluHttp::onError(QPointer<HttpCallable> callable,int status,QString errorString,QString result){
if (!callable.isNull()) {
Q_EMIT callable->error(status,errorString,result);
}
}
void FluHttp::onSuccess(QPointer<HttpCallable> callable,QString result){
if (!callable.isNull()) {
Q_EMIT callable->success(result);
}
}
void FluHttp::onCache(QPointer<HttpCallable> callable,QString result){
if (!callable.isNull()) {
Q_EMIT callable->cache(result);
}
}
void FluHttp::onDownloadProgress(QPointer<HttpCallable> callable,qint64 recv,qint64 total){
if (!callable.isNull()) {
Q_EMIT callable->downloadProgress(recv,total);
}
}
void FluHttp::onUploadProgress(QPointer<HttpCallable> callable,qint64 sent,qint64 total){
if (!callable.isNull()) {
Q_EMIT callable->uploadProgress(sent,total);
}
}

View File

@ -1,85 +0,0 @@
#ifndef FLUHTTP_H
#define FLUHTTP_H
#include <QObject>
#include <QtQml/qqml.h>
#include <QFile>
#include <QJsonValue>
#include <QNetworkAccessManager>
#include "stdafx.h"
class HttpRequest : public QObject{
Q_OBJECT
Q_PROPERTY_AUTO(QString,url);
# if (QT_VERSION == QT_VERSION_CHECK(6, 4, 3))
Q_PROPERTY_AUTO(QJsonValue,params);
Q_PROPERTY_AUTO(QJsonValue,headers);
# else
Q_PROPERTY_AUTO(QVariant,params);
Q_PROPERTY_AUTO(QVariant,headers);
# endif
Q_PROPERTY_AUTO(QString,method);
Q_PROPERTY_AUTO(QString,downloadSavePath);
QML_NAMED_ELEMENT(HttpRequest)
public:
explicit HttpRequest(QObject *parent = nullptr);
QMap<QString, QVariant> toMap();
Q_INVOKABLE QString httpId();
};
class HttpCallable : public QObject{
Q_OBJECT
QML_NAMED_ELEMENT(HttpCallable)
public:
explicit HttpCallable(QObject *parent = nullptr);
Q_SIGNAL void start();
Q_SIGNAL void finish();
Q_SIGNAL void error(int status,QString errorString,QString result);
Q_SIGNAL void success(QString result);
Q_SIGNAL void cache(QString result);
Q_SIGNAL void downloadProgress(qint64 recv, qint64 total);
Q_SIGNAL void uploadProgress(qint64 sent, qint64 total);
};
class FluHttp : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(int,retry);
Q_PROPERTY_AUTO(int,timeout)
Q_PROPERTY_AUTO(int,cacheMode);
Q_PROPERTY_AUTO(QString,cacheDir);
Q_PROPERTY_AUTO(bool,breakPointDownload);
QML_NAMED_ELEMENT(FluHttp)
private:
QVariant invokeIntercept(QMap<QString, QVariant> request);
void addQueryParam(QUrl* url,const QMap<QString, QVariant>& params);
void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& params);
void handleCache(const QString& httpId, const QString& result);
QString readCache(const QString& httpId);
bool cacheExists(const QString& httpId);
QString getCacheFilePath(const QString& httpId);
void onStart(QPointer<HttpCallable> callable);
void onFinish(QPointer<HttpCallable> callable,QPointer<HttpRequest> request);
void onError(QPointer<HttpCallable> callable,int status,QString errorString,QString result);
void onSuccess(QPointer<HttpCallable> callable,QString result);
void onCache(QPointer<HttpCallable> callable,QString result);
void onDownloadProgress(QPointer<HttpCallable> callable,qint64 recv,qint64 total);
void onUploadProgress(QPointer<HttpCallable> callable,qint64 sent,qint64 total);
public:
explicit FluHttp(QObject *parent = nullptr);
~FluHttp();
Q_INVOKABLE HttpRequest* newRequest(QString url = "");
Q_INVOKABLE void get(HttpRequest* request,HttpCallable* callable);
Q_INVOKABLE void post(HttpRequest* request,HttpCallable* callable);
Q_INVOKABLE void postString(HttpRequest* request,HttpCallable* callable);
Q_INVOKABLE void postJson(HttpRequest* request,HttpCallable* callable);
Q_INVOKABLE void download(HttpRequest* request,HttpCallable* callable);
Q_INVOKABLE void upload(HttpRequest* request,HttpCallable* callable);
Q_INVOKABLE void deleteResource(HttpRequest* request,HttpCallable* callable);
Q_INVOKABLE qreal getBreakPointProgress(HttpRequest* request);
Q_INVOKABLE void cancel();
private:
QList<QPointer<QNetworkReply>> _cacheReply;
};
#endif // FLUHTTP_H

View File

@ -1,4 +0,0 @@
#include "FluHttpInterceptor.h"
FluHttpInterceptor::FluHttpInterceptor(QObject *parent):QObject{parent}{
}

View File

@ -1,15 +0,0 @@
#ifndef FLUHTTPINTERCEPTOR_H
#define FLUHTTPINTERCEPTOR_H
#include <QObject>
#include <QtQml/qqml.h>
class FluHttpInterceptor : public QObject
{
Q_OBJECT
QML_NAMED_ELEMENT(FluHttpInterceptor)
public:
explicit FluHttpInterceptor(QObject *parent = nullptr);
};
#endif // FLUHTTPINTERCEPTOR_H

View File

@ -121,19 +121,22 @@ NetworkParams* NetworkParams::toDownload(QString destPath,bool append){
return this;
}
NetworkParams* NetworkParams::bind(QObject* target){
_target = target;
return this;
}
QString NetworkParams::buildCacheKey(){
QJsonObject obj;
obj.insert("url",_url);
obj.insert("method",method2String());
obj.insert("body",_body);
obj.insert("query",QString(QJsonDocument::fromVariant(_queryMap).toJson(QJsonDocument::Compact)));
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)));
obj.insert("query",QJsonDocument::fromVariant(_queryMap).object());
obj.insert("param",QJsonDocument::fromVariant(_paramMap).object());
obj.insert("header",QJsonDocument::fromVariant(_headerMap).object());
obj.insert("file",QJsonDocument::fromVariant(_fileMap).object());
if(_downloadParam){
QJsonObject downObj;
QString _destPath;
bool _append;
downObj.insert("destPath",_downloadParam->_destPath);
downObj.insert("append",_downloadParam->_append);
obj.insert("download",downObj);
@ -275,10 +278,16 @@ void FluNetwork::handleDownload(NetworkParams* params,NetworkCallable* c){
return;
}
}
reply = manager->get(request);
destFile->setParent(reply);
cacheFile->setParent(reply);
if(params->_target){
connect(params->_target,&QObject::destroyed,this,[reply]{
if(reply){
reply->abort();
}
});
}
connect(reply,&QNetworkReply::readyRead,reply,[reply,seek,destFile,cacheFile,callable]{
if (!reply || !destFile || reply->error() != QNetworkReply::NoError)
{

View File

@ -66,6 +66,7 @@ public:
Q_INVOKABLE NetworkParams* setRetry(int val);
Q_INVOKABLE NetworkParams* setCacheMode(int val);
Q_INVOKABLE NetworkParams* toDownload(QString destPath,bool append = false);
Q_INVOKABLE NetworkParams* bind(QObject* target);
Q_INVOKABLE void go(NetworkCallable* result);
QString buildCacheKey();
QString method2String();
@ -73,6 +74,7 @@ public:
int getRetry();
public:
DownloadParam* _downloadParam = nullptr;
QObject* _target = nullptr;
Method _method;
Type _type;
QString _url;

View File

@ -8,8 +8,6 @@
#include "FluTheme.h"
#include "FluTools.h"
#include "FluTextStyle.h"
#include "FluHttp.h"
#include "FluHttpInterceptor.h"
#include "FluWatermark.h"
#include "FluCaptcha.h"
#include "FluEventBus.h"
@ -36,10 +34,6 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterType<ScreenshotBackground>(uri,major,minor,"ScreenshotBackground");
qmlRegisterType<Screenshot>(uri,major,minor,"Screenshot");
qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet");
qmlRegisterType<FluHttpInterceptor>(uri,major,minor,"FluHttpInterceptor");
qmlRegisterType<FluHttp>(uri,major,minor,"FluHttp");
qmlRegisterType<HttpCallable>(uri,major,minor,"HttpCallable");
qmlRegisterType<HttpRequest>(uri,major,minor,"HttpRequest");
qmlRegisterType<FluEvent>(uri,major,minor,"FluEvent");
qmlRegisterType<FluViewModel>(uri,major,minor,"FluViewModel");
qmlRegisterType<FluTreeModel>(uri,major,minor,"FluTreeModel");
@ -144,7 +138,6 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterUncreatableMetaObject(Fluent_Awesome::staticMetaObject, uri,major,minor,"FluentIcons", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluHttpType::staticMetaObject, uri,major,minor,"FluHttpType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluThemeType::staticMetaObject, uri,major,minor,"FluThemeType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluPageType::staticMetaObject, uri,major,minor,"FluPageType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluWindowType::staticMetaObject, uri,major,minor,"FluWindowType", "Access to enums & flags only");