初步实现文件下载
parent
78865cd93c
commit
7c2db1bcc0
|
@ -61,7 +61,6 @@ QAbstractItemModel *FileTransferListModel::model()
|
|||
}
|
||||
|
||||
|
||||
|
||||
void FileTransferListModel::insertItem(const FileItem &item)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
|
@ -82,4 +81,10 @@ void FileTransferListModel::setItem(const FileItem &item)
|
|||
}
|
||||
}
|
||||
|
||||
FileTransferListModel &FileTransferListModel::instance()
|
||||
{
|
||||
static FileTransferListModel model;
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
#define AICSKNOWLEDGEBASE_FILETRANSFERLISTMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <curl/curl.h>
|
||||
#include <fstream>
|
||||
|
||||
struct FileItem
|
||||
{
|
||||
QString id;
|
||||
QString name;
|
||||
int completedSize;
|
||||
int totalSize;
|
||||
int64_t completedSize;
|
||||
int64_t totalSize;
|
||||
};
|
||||
|
||||
|
||||
|
@ -17,14 +19,14 @@ class FileTransferListModel : public QAbstractListModel
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FileTransferListModel(QObject *parent = nullptr);
|
||||
static FileTransferListModel& instance();
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
void insertItem(const FileItem &item);
|
||||
|
||||
|
@ -40,6 +42,8 @@ public:
|
|||
kTotalSizeRole
|
||||
};
|
||||
private:
|
||||
explicit FileTransferListModel(QObject *parent = nullptr);
|
||||
|
||||
QList<FileItem> m_data;
|
||||
QHash<int, QByteArray> m_roleName;
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <curl/curl.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <fstream>
|
||||
|
||||
static const std::string baseUrl = "http://127.0.0.1:4523/m1/2914957-0-default/";
|
||||
|
||||
|
@ -51,8 +52,8 @@ CURLcode httpGet(const std::string &url, std::string &response, int timeout = 30
|
|||
return res;
|
||||
}
|
||||
|
||||
FileTransferManager::FileTransferManager(FileTransferListModel &model, QObject *parent)
|
||||
: model(model), QObject(parent)
|
||||
FileTransferManager::FileTransferManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -96,6 +97,84 @@ void FileTransferManager::upload(QUrl fileUrl)
|
|||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
|
||||
struct FileTransfering : FileItem
|
||||
{
|
||||
CURL *curlHandle = nullptr;
|
||||
std::ofstream file;
|
||||
};
|
||||
|
||||
curl_off_t getHttpFileSize(const std::string &url)
|
||||
{
|
||||
curl_off_t fileLength = 0;
|
||||
|
||||
CURL *handle = curl_easy_init();
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(handle, CURLOPT_HEADER, 0); //只需要header头
|
||||
curl_easy_setopt(handle, CURLOPT_NOBODY, 1); //不需要body
|
||||
|
||||
if (curl_easy_perform(handle) == CURLE_OK)
|
||||
curl_easy_getinfo(handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &fileLength);
|
||||
else {
|
||||
qDebug() << "get file size error " << url.c_str();
|
||||
fileLength = -1;
|
||||
}
|
||||
curl_easy_cleanup(handle);
|
||||
return fileLength;
|
||||
}
|
||||
|
||||
size_t receiveDataFunc(const void *ptr, size_t size, size_t nmemb, void *obj)
|
||||
{
|
||||
auto buf = (FileTransfering *) obj;
|
||||
auto writeSize = size * nmemb;
|
||||
buf->file.write(reinterpret_cast<const char *>(ptr), writeSize);
|
||||
buf->completedSize += writeSize;
|
||||
qDebug() << std::format("Downloading: {} / {}", buf->completedSize, buf->totalSize).c_str();
|
||||
|
||||
QTimer::singleShot(0, qApp, [buf]() {
|
||||
FileTransferListModel::instance().setItem(static_cast<FileItem>(*buf));
|
||||
});
|
||||
|
||||
return writeSize;
|
||||
}
|
||||
|
||||
bool httpDownload(const std::string &url, const FileItem &item)
|
||||
{
|
||||
auto fileSize = getHttpFileSize(url);//获得文件大小。
|
||||
if (fileSize != -1) {
|
||||
qDebug() << "FileSize: " << fileSize;
|
||||
|
||||
FileTransfering obj = (FileTransfering) item;
|
||||
|
||||
obj.curlHandle = curl_easy_init();
|
||||
if (!obj.curlHandle)
|
||||
return false;
|
||||
obj.totalSize = fileSize;//原始文件大小
|
||||
obj.file = std::ofstream("D:\\Downloads\\" + obj.name.toStdString() + ".zip", std::ios::binary);
|
||||
|
||||
if (!obj.file.is_open()) {
|
||||
qDebug() << "Open File Failed";
|
||||
curl_easy_cleanup(obj.curlHandle);
|
||||
return false;
|
||||
} else {
|
||||
curl_easy_setopt(obj.curlHandle, CURLOPT_VERBOSE, 0L);
|
||||
curl_easy_setopt(obj.curlHandle, CURLOPT_HEADER, 0);
|
||||
curl_easy_setopt(obj.curlHandle, CURLOPT_NOPROGRESS, 1L);
|
||||
curl_easy_setopt(obj.curlHandle, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(obj.curlHandle, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(obj.curlHandle, CURLOPT_WRITEDATA, (void *) &obj);
|
||||
curl_easy_setopt(obj.curlHandle, CURLOPT_WRITEFUNCTION, receiveDataFunc);
|
||||
|
||||
//下载
|
||||
auto res = curl_easy_perform(obj.curlHandle);
|
||||
curl_easy_cleanup(obj.curlHandle);
|
||||
obj.file.close();
|
||||
return res == CURLE_OK && obj.completedSize == obj.totalSize;
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileTransferManager::download(QString fileId)
|
||||
{
|
||||
static int _fileId = 0;
|
||||
|
@ -103,6 +182,7 @@ void FileTransferManager::download(QString fileId)
|
|||
|
||||
QtConcurrent::run([fileId, this] {
|
||||
qDebug() << "Start Get";
|
||||
|
||||
std::string resData;
|
||||
if (CURLE_OK != httpGet(fileId.toStdString() + "/status", resData))
|
||||
return;
|
||||
|
@ -112,16 +192,29 @@ void FileTransferManager::download(QString fileId)
|
|||
//if(!resJson["isCompleted"].toBool())
|
||||
// return;
|
||||
|
||||
int size = resJson["size"].toInt();
|
||||
|
||||
|
||||
/* int size = resJson["size"].toInt();
|
||||
FileItem item{fileId, resJson["md5"].toString(), 0, size};
|
||||
QTimer::singleShot(0, qApp, [this, item]() {
|
||||
model.insertItem(item);
|
||||
FileTransferListModel::instance().insertItem(item);
|
||||
});*/
|
||||
|
||||
auto fileUrl = "https://curl.se/download/curl-8.1.2.zip";
|
||||
|
||||
int64_t size = getHttpFileSize(fileUrl);
|
||||
FileItem item{fileId, resJson["md5"].toString(), 0, size};
|
||||
QTimer::singleShot(0, qApp, [this, item]() {
|
||||
FileTransferListModel::instance().insertItem(item);
|
||||
});
|
||||
|
||||
while (item.completedSize < item.totalSize) {
|
||||
auto res = httpDownload(fileUrl, item);
|
||||
|
||||
|
||||
while (item.completedSize < item.totalSize && false) {
|
||||
item.completedSize += 1;
|
||||
QTimer::singleShot(0, qApp, [this, item]() {
|
||||
model.setItem(item);
|
||||
FileTransferListModel::instance().setItem(item);
|
||||
});
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
@ -129,7 +222,7 @@ void FileTransferManager::download(QString fileId)
|
|||
}
|
||||
|
||||
|
||||
qDebug() << "End Get";
|
||||
qDebug() << "End Get" << res;
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -14,14 +14,12 @@ class FileTransferManager : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FileTransferManager(FileTransferListModel &model, QObject *parent = nullptr);
|
||||
explicit FileTransferManager(QObject *parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void upload(QUrl fileUrl);
|
||||
|
||||
Q_INVOKABLE void download(QString fileId);
|
||||
|
||||
private:
|
||||
FileTransferListModel &model;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -45,11 +45,10 @@ int main(int argc, char *argv[])
|
|||
QQmlApplicationEngine engine;
|
||||
FramelessHelper::Quick::registerTypes(&engine);
|
||||
|
||||
FileTransferListModel fileTransferListModel;
|
||||
engine.rootContext()->setContextProperty("FileTransferListModel", &fileTransferListModel);
|
||||
engine.rootContext()->setContextProperty("FileTransferListModel", &FileTransferListModel::instance());
|
||||
|
||||
auto httpClient = new HttpClient(engine);
|
||||
auto fileTransferManager = new FileTransferManager(fileTransferListModel);
|
||||
auto fileTransferManager = new FileTransferManager();
|
||||
|
||||
qmlRegisterSingletonInstance<HttpClient>("AicsKB.HttpClient", 1, 0, "HttpClient", httpClient);
|
||||
qmlRegisterSingletonInstance<FileTransferManager>("AicsKB.FileTransferManager", 1, 0, "FileTransferManager",
|
||||
|
|
Loading…
Reference in New Issue