This commit is contained in:
zhuzichu 2023-08-16 13:14:00 +08:00
parent 79d29769e1
commit 1b72b840d6
5 changed files with 150 additions and 20 deletions

View File

@ -133,6 +133,15 @@ FluContentPage{
implicitWidth: parent.width implicitWidth: parent.width
implicitHeight: 36 implicitHeight: 36
text: "下载文件" text: "下载文件"
onClicked: {
folder_dialog.open()
}
}
FluButton{
id:btn_upload
implicitWidth: parent.width
implicitHeight: 36
text: "文件上传"
onClicked: { onClicked: {
file_dialog.open() file_dialog.open()
} }
@ -140,8 +149,48 @@ FluContentPage{
} }
} }
FolderDialog { FileDialog {
id: file_dialog id: file_dialog
onAccepted: {
var param = {}
for(var i=0;i<selectedFiles.length;i++){
var fileUrl = selectedFiles[i]
var fileName = FluTools.getFileNameByUrl(fileUrl)
var filePath = FluTools.toLocalPath(fileUrl)
param[fileName] = filePath
}
console.debug(JSON.stringify(param))
var callable = {}
callable.onStart = function(){
btn_upload.disabled = true
}
callable.onFinish = function(){
btn_upload.disabled = false
btn_upload.text = "上传文件"
layout_upload_file_size.visible = false
text_upload_file_size.text = ""
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString,result){
text_info.text = result
console.debug(result)
}
callable.onUploadProgress = function(sent,total){
var locale = Qt.locale()
var precent = (sent/total * 100).toFixed(0) + "%"
btn_upload.text = "上传中..."+precent
text_upload_file_size.text = "%1/%2".arg(locale.formattedDataSize(sent)).arg(locale.formattedDataSize(total))
layout_upload_file_size.visible = true
}
http.upload("https://httpbingo.org/post",callable,param)
}
}
FolderDialog {
id: folder_dialog
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0] currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
onAccepted: { onAccepted: {
var callable = {} var callable = {}
@ -151,8 +200,8 @@ FluContentPage{
callable.onFinish = function(){ callable.onFinish = function(){
btn_download.disabled = false btn_download.disabled = false
btn_download.text = "下载文件" btn_download.text = "下载文件"
layout_file_size.visible = false layout_download_file_size.visible = false
text_file_size.text = "" text_download_file_size.text = ""
} }
callable.onSuccess = function(result){ callable.onSuccess = function(result){
showSuccess(result) showSuccess(result)
@ -164,8 +213,8 @@ FluContentPage{
var locale = Qt.locale() var locale = Qt.locale()
var precent = (recv/total * 100).toFixed(0) + "%" var precent = (recv/total * 100).toFixed(0) + "%"
btn_download.text = "下载中..."+precent btn_download.text = "下载中..."+precent
text_file_size.text = "%1/%2".arg(locale.formattedDataSize(recv)).arg(locale.formattedDataSize(total)) text_download_file_size.text = "%1/%2".arg(locale.formattedDataSize(recv)).arg(locale.formattedDataSize(total))
layout_file_size.visible = true layout_download_file_size.visible = true
} }
var path = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4" var path = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4"
http.download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",callable,path) http.download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",callable,path)
@ -183,6 +232,7 @@ FluContentPage{
Flickable{ Flickable{
clip: true clip: true
id:scrollview id:scrollview
boundsBehavior:Flickable.StopAtBounds
width: parent.width width: parent.width
height: parent.height height: parent.height
contentWidth: width contentWidth: width
@ -198,7 +248,7 @@ FluContentPage{
} }
FluRectangle{ FluRectangle{
id:layout_file_size id:layout_download_file_size
radius: [4,4,4,4] radius: [4,4,4,4]
height: 36 height: 36
width: 160 width: 160
@ -206,7 +256,22 @@ FluContentPage{
x:layout_flick.width x:layout_flick.width
y: 173 - layout_flick.contentY y: 173 - layout_flick.contentY
FluText{ FluText{
id:text_file_size id:text_download_file_size
anchors.centerIn: parent
}
}
FluRectangle{
id:layout_upload_file_size
radius: [4,4,4,4]
height: 36
width: 160
visible: false
x:layout_flick.width
y: 210 - layout_flick.contentY
FluText{
id:text_upload_file_size
anchors.centerIn: parent anchors.centerIn: parent
} }
} }

View File

@ -43,8 +43,6 @@ void FluHttp::post(QString url,QJSValue callable,QMap<QString, QVariant> params,
QNetworkRequest request(_url); QNetworkRequest request(_url);
addHeaders(&request,data["headers"].toMap()); addHeaders(&request,data["headers"].toMap());
QHttpMultiPart multiPart(QHttpMultiPart::FormDataType); QHttpMultiPart multiPart(QHttpMultiPart::FormDataType);
QString contentType = QString("multipart/form-data;boundary=%1").arg(multiPart.boundary());
request.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
for (const auto& each : data["params"].toMap().toStdMap()) for (const auto& each : data["params"].toMap().toStdMap())
{ {
const QString& key = each.first; const QString& key = each.first;
@ -74,7 +72,7 @@ void FluHttp::post(QString url,QJSValue callable,QMap<QString, QVariant> params,
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString); onError(callable,status,errorString,result);
} }
} }
} }
@ -113,7 +111,7 @@ void FluHttp::postString(QString url,QJSValue callable,QString params,QMap<QStri
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString); onError(callable,status,errorString,result);
} }
} }
} }
@ -152,7 +150,7 @@ void FluHttp::postJson(QString url,QJSValue callable,QMap<QString, QVariant> par
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString); onError(callable,status,errorString,result);
} }
} }
} }
@ -190,7 +188,7 @@ void FluHttp::get(QString url,QJSValue callable,QMap<QString, QVariant> params,Q
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString); onError(callable,status,errorString,result);
} }
} }
} }
@ -211,7 +209,7 @@ void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap<QStri
QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate; QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate;
if (!file->open(mode)) if (!file->open(mode))
{ {
onError(callable,-1,QString("Url: %1 %2 Non-Writable").arg(request.url().toString(),file->fileName())); onError(callable,-1,QString("Url: %1 %2 Non-Writable").arg(request.url().toString(),file->fileName()),"");
onFinish(callable); onFinish(callable);
return; return;
} }
@ -229,7 +227,7 @@ void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap<QStri
file->write(reply->readAll()); file->write(reply->readAll());
onSuccess(callable,filePath); onSuccess(callable,filePath);
}else{ }else{
onError(callable,reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),reply->errorString()); onError(callable,reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),reply->errorString(),"");
} }
_cache.removeOne(reply); _cache.removeOne(reply);
reply->deleteLater(); reply->deleteLater();
@ -238,6 +236,56 @@ void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap<QStri
}); });
} }
void FluHttp::upload(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
QMap<QString, QVariant> data = invokeIntercept(params,headers,"upload").toMap();
QThreadPool::globalInstance()->start([=](){
onStart(callable);
QNetworkAccessManager manager;
manager.setTransferTimeout(timeout());
QUrl _url(url);
QNetworkRequest request(_url);
addHeaders(&request,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);
}
QEventLoop loop;
QNetworkReply* reply = manager.post(request,&multiPart);
_cache.append(reply);
connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){
loop.quit();
});
connect(reply,&QNetworkReply::uploadProgress,this,[=](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;
_cache.removeOne(reply);
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
onSuccess(callable,result);
}else{
onError(callable,status,errorString,result);
}
onFinish(callable);
});
}
QVariant FluHttp::invokeIntercept(const QVariant& params,const QVariant& headers,const QString& method){ QVariant FluHttp::invokeIntercept(const QVariant& params,const QVariant& headers,const QString& method){
QMap<QString, QVariant> requet = { QMap<QString, QVariant> requet = {
{"params",params}, {"params",params},
@ -282,10 +330,10 @@ void FluHttp::onFinish(const QJSValue& callable){
MainThread::post([=](){onFinish.call();}); MainThread::post([=](){onFinish.call();});
} }
void FluHttp::onError(const QJSValue& callable,int status,QString errorString){ void FluHttp::onError(const QJSValue& callable,int status,QString errorString,QString result){
QJSValue onError = callable.property("onError"); QJSValue onError = callable.property("onError");
QJSValueList args; QJSValueList args;
args<<status<<errorString; args<<status<<errorString<<result;
MainThread::post([=](){onError.call(args);}); MainThread::post([=](){onError.call(args);});
} }
@ -303,3 +351,11 @@ void FluHttp::onDownloadProgress(const QJSValue& callable,qint64 recv, qint64 to
QJSValue onDownloadProgress = callable.property("onDownloadProgress"); QJSValue onDownloadProgress = callable.property("onDownloadProgress");
MainThread::post([=](){onDownloadProgress.call(args);}); MainThread::post([=](){onDownloadProgress.call(args);});
} }
void FluHttp::onUploadProgress(const QJSValue& callable,qint64 sent, qint64 total){
QJSValueList args;
args<<static_cast<double>(sent);
args<<static_cast<double>(total);
QJSValue onUploadProgress = callable.property("onUploadProgress");
MainThread::post([=](){onUploadProgress.call(args);});
}

View File

@ -20,18 +20,20 @@ private:
void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& params); void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& params);
void onStart(const QJSValue& callable); void onStart(const QJSValue& callable);
void onFinish(const QJSValue& callable); void onFinish(const QJSValue& callable);
void onError(const QJSValue& callable,int status,QString errorString); void onError(const QJSValue& callable,int status,QString errorString,QString result);
void onSuccess(const QJSValue& callable,QString result); void onSuccess(const QJSValue& callable,QString result);
void onDownloadProgress(const QJSValue& callable,qint64 recv, qint64 total); void onDownloadProgress(const QJSValue& callable,qint64 recv, qint64 total);
void onUploadProgress(const QJSValue& callable,qint64 recv, qint64 total);
public: public:
explicit FluHttp(QObject *parent = nullptr); explicit FluHttp(QObject *parent = nullptr);
~FluHttp(); ~FluHttp();
//神坑!!! 如果参数使用QVariantMap会有问题在6.4.3版本中QML一调用就会编译失败。所以改用QMap<QString, QVariant> //神坑!!! 如果参数使用QVariantMap会有问题在6.4.3版本中QML一调用就会编译失败。所以改用QMap<QString, QVariant>
Q_INVOKABLE void get(QString url,QJSValue callable,QMap<QString, QVariant> = {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void get(QString url,QJSValue callable,QMap<QString, QVariant> params= {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void post(QString url,QJSValue callable,QMap<QString, QVariant> = {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void post(QString url,QJSValue callable,QMap<QString, QVariant> params= {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void postString(QString url,QJSValue callable,QString params = "",QMap<QString, QVariant> headers = {}); Q_INVOKABLE void postString(QString url,QJSValue callable,QString params = "",QMap<QString, QVariant> headers = {});
Q_INVOKABLE void postJson(QString url,QJSValue callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void postJson(QString url,QJSValue callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void download(QString url,QJSValue callable,QString filePath,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void download(QString url,QJSValue callable,QString filePath,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void upload(QString url,QJSValue callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void cancel(); Q_INVOKABLE void cancel();
private: private:
QList<QPointer<QNetworkReply>> _cache; QList<QPointer<QNetworkReply>> _cache;

View File

@ -3,6 +3,7 @@
#include <QClipboard> #include <QClipboard>
#include <QUuid> #include <QUuid>
#include <QCursor> #include <QCursor>
#include <QFileInfo>
#include <QTextDocument> #include <QTextDocument>
FluTools* FluTools::m_instance = nullptr; FluTools* FluTools::m_instance = nullptr;
@ -100,6 +101,10 @@ QString FluTools::toLocalPath(const QUrl& url){
return url.toLocalFile(); return url.toLocalFile();
} }
QString FluTools::getFileNameByUrl(const QUrl& url){
return QFileInfo(url.toLocalFile()).fileName();
}
QString FluTools::html2PlantText(const QString& html){ QString FluTools::html2PlantText(const QString& html){
QTextDocument textDocument; QTextDocument textDocument;
textDocument.setHtml(html); textDocument.setHtml(html);

View File

@ -103,6 +103,8 @@ public:
*/ */
Q_INVOKABLE QString toLocalPath(const QUrl& url); Q_INVOKABLE QString toLocalPath(const QUrl& url);
Q_INVOKABLE QString getFileNameByUrl(const QUrl& url);
/** /**
* @brief deleteItem Item对象 * @brief deleteItem Item对象
* @param p * @param p