实现上传进度显示
parent
5c1b23421c
commit
3535f3ee03
|
@ -4,6 +4,7 @@ import FluentUI
|
||||||
import QtQuick.Dialogs
|
import QtQuick.Dialogs
|
||||||
import "qrc:///AicsKnowledgeBase/qml/global"
|
import "qrc:///AicsKnowledgeBase/qml/global"
|
||||||
import SignalFileOperation 1.0
|
import SignalFileOperation 1.0
|
||||||
|
import AicsKB.FileTransferManager
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -53,13 +54,14 @@ Item {
|
||||||
FileDialog {
|
FileDialog {
|
||||||
id: fileDialog
|
id: fileDialog
|
||||||
onAccepted: function () {
|
onAccepted: function () {
|
||||||
|
let name = FileTransferManager.getFileName(selectedFile)
|
||||||
const size = FileTransferManager.getFileSize(
|
const size = FileTransferManager.getFileSize(
|
||||||
selectedFile)
|
selectedFile)
|
||||||
const md5 = FileTransferManager.getFileMd5(selectedFile)
|
const md5 = FileTransferManager.getFileMd5(selectedFile)
|
||||||
if (size <= 0 || md5 === '')
|
if (size <= 0 || md5 === '')
|
||||||
return
|
return
|
||||||
var body = {
|
var body = {
|
||||||
"name": "test2",
|
"name": name,
|
||||||
"brief": "brief",
|
"brief": "brief",
|
||||||
"size": size,
|
"size": size,
|
||||||
"md5": md5,
|
"md5": md5,
|
||||||
|
@ -75,7 +77,7 @@ Item {
|
||||||
console.log(data)
|
console.log(data)
|
||||||
FileTransferManager.upload(
|
FileTransferManager.upload(
|
||||||
selectedFile, data.id,
|
selectedFile, data.id,
|
||||||
data.ticket)
|
data.ticket, name)
|
||||||
}, function (res, data) {
|
}, function (res, data) {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,6 @@ import QtQuick.Controls
|
||||||
import QtQuick.Controls.Basic
|
import QtQuick.Controls.Basic
|
||||||
import QtQuick.Dialogs
|
import QtQuick.Dialogs
|
||||||
import FluentUI
|
import FluentUI
|
||||||
import AicsKB.FileTransferManager
|
|
||||||
import "qrc:///AicsKnowledgeBase/qml/component"
|
import "qrc:///AicsKnowledgeBase/qml/component"
|
||||||
import "qrc:///AicsKnowledgeBase/qml/global"
|
import "qrc:///AicsKnowledgeBase/qml/global"
|
||||||
|
|
||||||
|
|
|
@ -3,20 +3,13 @@
|
||||||
FileTransferListModel::FileTransferListModel(QObject *parent)
|
FileTransferListModel::FileTransferListModel(QObject *parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
|
m_roleName.insert(kDownloadRole, "download");
|
||||||
m_roleName.insert(kIdRole, "fileId");
|
m_roleName.insert(kIdRole, "fileId");
|
||||||
m_roleName.insert(kNameRole, "name");
|
m_roleName.insert(kNameRole, "name");
|
||||||
m_roleName.insert(kCompletedSizeRole, "completedSize");
|
m_roleName.insert(kCompletedSizeRole, "completedSize");
|
||||||
m_roleName.insert(kTotalSizeRole, "totalSize");
|
m_roleName.insert(kTotalSizeRole, "totalSize");
|
||||||
m_roleName.insert(kSpeedRole, "speed");
|
m_roleName.insert(kSpeedRole, "speed");
|
||||||
m_roleName.insert(kPausedRole, "paused");
|
m_roleName.insert(kPausedRole, "paused");
|
||||||
|
|
||||||
m_data = {
|
|
||||||
{"v", "vivo", 1200, 2000},
|
|
||||||
{"m", "meizu", 1300, 1500},
|
|
||||||
{"a", "apple", 1400, 1400},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,6 +29,8 @@ QVariant FileTransferListModel::data(const QModelIndex &index, int role) const
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
|
case kDownloadRole:
|
||||||
|
return m_data.value(index.row()).download;
|
||||||
case kIdRole:
|
case kIdRole:
|
||||||
return m_data.value(index.row()).id;
|
return m_data.value(index.row()).id;
|
||||||
case kNameRole:
|
case kNameRole:
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
struct FileItem
|
struct FileItem
|
||||||
{
|
{
|
||||||
|
bool download = true;
|
||||||
QString id;
|
QString id;
|
||||||
QString name;
|
QString name;
|
||||||
int64_t completedSize;
|
int64_t completedSize;
|
||||||
|
@ -38,7 +39,8 @@ public:
|
||||||
|
|
||||||
enum FileItemRole
|
enum FileItemRole
|
||||||
{
|
{
|
||||||
kIdRole = Qt::UserRole + 1,
|
kDownloadRole = Qt::UserRole + 1,
|
||||||
|
kIdRole,
|
||||||
kNameRole,
|
kNameRole,
|
||||||
kCompletedSizeRole,
|
kCompletedSizeRole,
|
||||||
kTotalSizeRole,
|
kTotalSizeRole,
|
||||||
|
|
|
@ -13,6 +13,88 @@ static const std::string baseUrl = "https://api.hammer-hfut.tk:233/aics/file/";
|
||||||
//static const std::string baseUrl = "http://127.0.0.1:4523/m1/2914957-0-6e5f2db1/";
|
//static const std::string baseUrl = "http://127.0.0.1:4523/m1/2914957-0-6e5f2db1/";
|
||||||
//static const std::string baseUrl = "https://quic.nginx.org/";
|
//static const std::string baseUrl = "https://quic.nginx.org/";
|
||||||
|
|
||||||
|
struct FileDownloading : FileItem
|
||||||
|
{
|
||||||
|
CURL *curlHandle = nullptr;
|
||||||
|
std::ofstream file;
|
||||||
|
};
|
||||||
|
std::unordered_map<QString, FileDownloading> downloadingMap;
|
||||||
|
std::mutex downloadingMapMutex;
|
||||||
|
|
||||||
|
struct FileUploading : FileItem
|
||||||
|
{
|
||||||
|
CURL *curlHandle = nullptr;
|
||||||
|
std::ifstream file;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<QString, FileUploading> uploadingMap;
|
||||||
|
std::mutex uploadingMapMutex;
|
||||||
|
|
||||||
|
size_t writeDataFunc(const void *ptr, size_t size, size_t nmemb, void *obj)
|
||||||
|
{
|
||||||
|
auto buf = (FileDownloading *) obj;
|
||||||
|
auto writeSize = size * nmemb;
|
||||||
|
buf->file.write(reinterpret_cast<const char *>(ptr), writeSize);
|
||||||
|
return writeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t readDataFunc(void *ptr, size_t size, size_t nmemb, void *obj)
|
||||||
|
{
|
||||||
|
auto buf = (FileUploading *) obj;
|
||||||
|
auto readSize = size * nmemb;
|
||||||
|
buf->file.read(reinterpret_cast<char *>(ptr), readSize);
|
||||||
|
return readSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
||||||
|
{
|
||||||
|
auto fileTrans = (FileDownloading *) p;
|
||||||
|
curl_off_t speed = 0;
|
||||||
|
|
||||||
|
curl_easy_getinfo(fileTrans->curlHandle, CURLINFO_SPEED_DOWNLOAD_T, &speed);
|
||||||
|
|
||||||
|
fileTrans->completedSize += dlnow;
|
||||||
|
|
||||||
|
fileTrans->speed = speed;
|
||||||
|
qDebug() << std::format("Downloading: {} / {}, Speed: {}", fileTrans->completedSize, fileTrans->totalSize,
|
||||||
|
speed).c_str();
|
||||||
|
|
||||||
|
auto item = static_cast<FileItem>(*fileTrans);
|
||||||
|
QTimer::singleShot(0, qApp, [item]() {
|
||||||
|
FileTransferListModel::instance().setItem(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fileTrans->paused) {
|
||||||
|
qDebug() << "Pause";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fileTrans->completedSize -= dlnow;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int uploadInfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
||||||
|
{
|
||||||
|
auto fileTrans = (FileUploading *) p;
|
||||||
|
curl_off_t speed = 0;
|
||||||
|
curl_easy_getinfo(fileTrans->curlHandle, CURLINFO_SPEED_UPLOAD_T, &speed);
|
||||||
|
fileTrans->completedSize += ulnow;
|
||||||
|
fileTrans->speed = speed;
|
||||||
|
qDebug() << std::format("Uploading: {} / {}, Speed: {}", fileTrans->completedSize, fileTrans->totalSize,
|
||||||
|
speed).c_str();
|
||||||
|
|
||||||
|
auto item = static_cast<FileItem>(*fileTrans);
|
||||||
|
QTimer::singleShot(0, qApp, [item]() {
|
||||||
|
FileTransferListModel::instance().setItem(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fileTrans->paused) {
|
||||||
|
qDebug() << "Pause";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fileTrans->completedSize -= ulnow;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t writeDataCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
static size_t writeDataCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -60,74 +142,88 @@ FileTransferManager::FileTransferManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
std::string resData;
|
std::string resData;
|
||||||
if (CURLE_OK == httpGet("file/hello", resData))
|
if (CURLE_OK == httpGet("hello", resData))
|
||||||
qDebug() << "HTTP3 OK\n" << resData.c_str();
|
qDebug() << "HTTP3 OK\n" << resData.c_str();
|
||||||
else
|
else
|
||||||
qDebug() << "HTTP3 FAILED";
|
qDebug() << "HTTP3 FAILED";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t completedSize = 0;
|
void
|
||||||
|
FileTransferManager::upload(const QUrl &fileUrl, const QString &fileId, const QString &ticket, const QString &fileName)
|
||||||
size_t readDataFunc(void *ptr, size_t size, size_t nmemb, void *file)
|
|
||||||
{
|
|
||||||
auto s = reinterpret_cast<QFile *>(file)->read(reinterpret_cast<char *>(ptr),
|
|
||||||
size * nmemb);
|
|
||||||
completedSize += s;
|
|
||||||
qDebug() << std::format("Uploading: {} / {}", completedSize,
|
|
||||||
reinterpret_cast<QFile *>(file)->size()).c_str();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransferManager::upload(const QUrl &fileUrl, const QString &fileId, const QString &ticket)
|
|
||||||
{
|
{
|
||||||
qDebug() << fileUrl.fileName();
|
qDebug() << fileUrl.fileName();
|
||||||
|
|
||||||
QFile file = fileUrl.toLocalFile();
|
QtConcurrent::run([fileUrl, fileId, ticket, fileName] {
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
return;
|
|
||||||
auto fileSize = file.size();
|
|
||||||
|
|
||||||
CURLcode res;
|
|
||||||
CURL *curl = curl_easy_init();
|
|
||||||
if (!curl)
|
|
||||||
return;
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, (baseUrl + "file/" + fileId.toStdString()).c_str());
|
auto fileSize = QFileInfo(fileUrl.toLocalFile()).size();
|
||||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3ONLY);
|
|
||||||
curl_httppost *formpost = nullptr;
|
|
||||||
curl_httppost *lastptr = nullptr;
|
|
||||||
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "ticket",
|
|
||||||
CURLFORM_COPYCONTENTS, ticket.toStdString().c_str(),
|
|
||||||
CURLFORM_END);
|
|
||||||
|
|
||||||
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "rangeStart",
|
FileItem item{false, fileId, fileName, 0, fileSize};
|
||||||
CURLFORM_COPYCONTENTS, std::to_string(0).c_str(),
|
QTimer::singleShot(0, qApp, [item]() {
|
||||||
CURLFORM_END);
|
FileTransferListModel::instance().insertItem(item);
|
||||||
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "rangeEnd",
|
});
|
||||||
CURLFORM_COPYCONTENTS, std::to_string(fileSize).c_str(),
|
|
||||||
CURLFORM_END);
|
|
||||||
|
|
||||||
curl_formadd(&formpost, &lastptr,
|
uploadingMapMutex.lock();
|
||||||
CURLFORM_COPYNAME, "data",
|
auto [iter, _] = uploadingMap.emplace(item.id, (FileUploading) item);
|
||||||
CURLFORM_STREAM, &file,
|
uploadingMapMutex.unlock();
|
||||||
CURLFORM_CONTENTLEN, fileSize,
|
|
||||||
CURLFORM_END);
|
FileUploading &fileUploading = iter->second;
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
|
fileUploading.file = std::ifstream(fileUrl.toLocalFile().toLocal8Bit().toStdString(), std::ios::binary);
|
||||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, readDataFunc);
|
|
||||||
qDebug() << "Begin Upload";
|
if (!fileUploading.file.is_open()) {
|
||||||
completedSize = 0;
|
qDebug() << "Open File Failed";
|
||||||
res = curl_easy_perform(curl);
|
return false;
|
||||||
if (res == CURLE_OK)
|
}
|
||||||
qDebug() << "Upload Success";
|
|
||||||
else
|
CURLcode res;
|
||||||
qDebug() << "Upload Failed";
|
fileUploading.curlHandle = curl_easy_init();
|
||||||
curl_easy_cleanup(curl);
|
if (!fileUploading.curlHandle)
|
||||||
curl_formfree(formpost);
|
return false;
|
||||||
file.close();
|
|
||||||
|
curl_httppost *formpost = nullptr;
|
||||||
|
curl_httppost *lastptr = nullptr;
|
||||||
|
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "ticket",
|
||||||
|
CURLFORM_COPYCONTENTS, ticket.toStdString().c_str(),
|
||||||
|
CURLFORM_END);
|
||||||
|
|
||||||
|
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "rangeStart",
|
||||||
|
CURLFORM_COPYCONTENTS, std::to_string(0).c_str(),
|
||||||
|
CURLFORM_END);
|
||||||
|
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "rangeEnd",
|
||||||
|
CURLFORM_COPYCONTENTS, std::to_string(fileSize).c_str(),
|
||||||
|
CURLFORM_END);
|
||||||
|
|
||||||
|
curl_formadd(&formpost, &lastptr,
|
||||||
|
CURLFORM_COPYNAME, "data",
|
||||||
|
CURLFORM_STREAM, &fileUploading,
|
||||||
|
CURLFORM_CONTENTLEN, fileSize,
|
||||||
|
CURLFORM_END);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_URL, (baseUrl + fileId.toStdString()).c_str());
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_VERBOSE, 1L);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3ONLY);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_HTTPPOST, formpost);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_READFUNCTION, readDataFunc);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_NOPROGRESS, false);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_XFERINFOFUNCTION, uploadInfo);
|
||||||
|
curl_easy_setopt(fileUploading.curlHandle, CURLOPT_XFERINFODATA, &fileUploading);
|
||||||
|
|
||||||
|
qDebug() << "Begin Upload";
|
||||||
|
|
||||||
|
res = curl_easy_perform(fileUploading.curlHandle);
|
||||||
|
if (res == CURLE_OK)
|
||||||
|
qDebug() << "Upload Success";
|
||||||
|
else
|
||||||
|
qDebug() << "Upload Failed";
|
||||||
|
curl_easy_cleanup(fileUploading.curlHandle);
|
||||||
|
curl_formfree(formpost);
|
||||||
|
fileUploading.file.close();
|
||||||
|
|
||||||
|
uploadingMapMutex.lock();
|
||||||
|
uploadingMap.erase(fileId);
|
||||||
|
uploadingMapMutex.unlock();
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,104 +247,53 @@ curl_off_t getHttpFileSize(const std::string &url)
|
||||||
return fileLength;
|
return fileLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileTransfering : FileItem
|
|
||||||
{
|
|
||||||
CURL *curlHandle = nullptr;
|
|
||||||
std::ofstream file;
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
return writeSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
|
||||||
{
|
|
||||||
auto fileTrans = (FileTransfering *) p;
|
|
||||||
curl_off_t speed = 0;
|
|
||||||
|
|
||||||
curl_easy_getinfo(fileTrans->curlHandle, CURLINFO_SPEED_DOWNLOAD_T, &speed);
|
|
||||||
|
|
||||||
fileTrans->completedSize += dlnow;
|
|
||||||
|
|
||||||
fileTrans->speed = speed;
|
|
||||||
qDebug() << std::format("Downloading: {} / {}, Speed: {}", fileTrans->completedSize, fileTrans->totalSize,
|
|
||||||
speed).c_str();
|
|
||||||
|
|
||||||
auto item = static_cast<FileItem>(*fileTrans);
|
|
||||||
QTimer::singleShot(0, qApp, [item]() {
|
|
||||||
FileTransferListModel::instance().setItem(item);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (fileTrans->paused) {
|
|
||||||
qDebug() << "Pause";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fileTrans->completedSize -= dlnow;
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::unordered_map<QString, FileTransfering> transferMap;
|
|
||||||
|
|
||||||
std::mutex transferMapMutex;
|
|
||||||
|
|
||||||
bool httpDownload(const std::string &url, const FileItem &item)
|
bool httpDownload(const std::string &url, const FileItem &item)
|
||||||
{
|
{
|
||||||
auto fileSize = getHttpFileSize(url);//获得文件大小。
|
auto fileSize = getHttpFileSize(url);//获得文件大小。
|
||||||
if (fileSize != -1) {
|
if (fileSize == -1)
|
||||||
qDebug() << "FileSize: " << fileSize;
|
|
||||||
|
|
||||||
transferMapMutex.lock();
|
|
||||||
auto [iter, _] = transferMap.emplace(item.id, (FileTransfering) item);
|
|
||||||
transferMapMutex.unlock();
|
|
||||||
|
|
||||||
FileTransfering &obj = iter->second;
|
|
||||||
|
|
||||||
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_FOLLOWLOCATION, 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);
|
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_NOPROGRESS, false);//设为false 下面才能设置进度响应函数
|
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_XFERINFOFUNCTION, xferinfo);
|
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_XFERINFODATA, &obj);
|
|
||||||
|
|
||||||
//下载
|
|
||||||
auto res = curl_easy_perform(obj.curlHandle);
|
|
||||||
curl_easy_cleanup(obj.curlHandle);
|
|
||||||
obj.file.close();
|
|
||||||
|
|
||||||
transferMapMutex.lock();
|
|
||||||
transferMap.erase(obj.id);
|
|
||||||
transferMapMutex.unlock();
|
|
||||||
|
|
||||||
return res == CURLE_OK;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
qDebug() << "FileSize: " << fileSize;
|
||||||
|
|
||||||
|
downloadingMapMutex.lock();
|
||||||
|
auto [iter, _] = downloadingMap.emplace(item.id, (FileDownloading) item);
|
||||||
|
downloadingMapMutex.unlock();
|
||||||
|
|
||||||
|
FileDownloading &obj = iter->second;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(obj.curlHandle, CURLOPT_VERBOSE, 0L);
|
||||||
|
curl_easy_setopt(obj.curlHandle, CURLOPT_HEADER, 0);
|
||||||
|
curl_easy_setopt(obj.curlHandle, CURLOPT_NOSIGNAL, 1L);
|
||||||
|
curl_easy_setopt(obj.curlHandle, CURLOPT_FOLLOWLOCATION, 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, writeDataFunc);
|
||||||
|
curl_easy_setopt(obj.curlHandle, CURLOPT_NOPROGRESS, false);//设为false 下面才能设置进度响应函数
|
||||||
|
curl_easy_setopt(obj.curlHandle, CURLOPT_XFERINFOFUNCTION, xferinfo);
|
||||||
|
curl_easy_setopt(obj.curlHandle, CURLOPT_XFERINFODATA, &obj);
|
||||||
|
|
||||||
|
//下载
|
||||||
|
auto res = curl_easy_perform(obj.curlHandle);
|
||||||
|
curl_easy_cleanup(obj.curlHandle);
|
||||||
|
obj.file.close();
|
||||||
|
|
||||||
|
downloadingMapMutex.lock();
|
||||||
|
downloadingMap.erase(obj.id);
|
||||||
|
downloadingMapMutex.unlock();
|
||||||
|
|
||||||
|
return res == CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileTransferManager::download(QString fileId)
|
void FileTransferManager::download(QString fileId)
|
||||||
|
@ -285,7 +330,7 @@ void FileTransferManager::download(QString fileId)
|
||||||
|
|
||||||
|
|
||||||
int64_t size = getHttpFileSize(fileUrl);
|
int64_t size = getHttpFileSize(fileUrl);
|
||||||
FileItem item{fileId, fileId, 0, size};
|
FileItem item{true, fileId, fileId, 0, size};
|
||||||
|
|
||||||
auto res = httpDownload(fileUrl, item);
|
auto res = httpDownload(fileUrl, item);
|
||||||
|
|
||||||
|
@ -298,9 +343,9 @@ void FileTransferManager::download(QString fileId)
|
||||||
|
|
||||||
void FileTransferManager::pause(const QString &fileId)
|
void FileTransferManager::pause(const QString &fileId)
|
||||||
{
|
{
|
||||||
transferMapMutex.lock();
|
downloadingMapMutex.lock();
|
||||||
transferMap[fileId].paused = true;
|
downloadingMap[fileId].paused = true;
|
||||||
transferMapMutex.unlock();
|
downloadingMapMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileTransferManager::getFileMd5(const QUrl &fileUrl)
|
QString FileTransferManager::getFileMd5(const QUrl &fileUrl)
|
||||||
|
@ -358,7 +403,7 @@ void FileTransferManager::resume(const QString &fileId)
|
||||||
|
|
||||||
|
|
||||||
int64_t size = getHttpFileSize(fileUrl);
|
int64_t size = getHttpFileSize(fileUrl);
|
||||||
FileItem item{fileId, fileId, 0, size};
|
FileItem item{true, fileId, fileId, 0, size};
|
||||||
QTimer::singleShot(0, qApp, [this, item]() {
|
QTimer::singleShot(0, qApp, [this, item]() {
|
||||||
FileTransferListModel::instance().insertItem(item);
|
FileTransferListModel::instance().insertItem(item);
|
||||||
});
|
});
|
||||||
|
@ -371,3 +416,8 @@ void FileTransferManager::resume(const QString &fileId)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString FileTransferManager::getFileName(const QUrl &fileUrl)
|
||||||
|
{
|
||||||
|
return fileUrl.fileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,10 @@ Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit FileTransferManager(QObject *parent = nullptr);
|
explicit FileTransferManager(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Q_INVOKABLE QString getFileName(const QUrl& fileUrl);
|
||||||
Q_INVOKABLE int64_t getFileSize(const QUrl& fileUrl);
|
Q_INVOKABLE int64_t getFileSize(const QUrl& fileUrl);
|
||||||
Q_INVOKABLE QString getFileMd5(const QUrl& fileUrl);
|
Q_INVOKABLE QString getFileMd5(const QUrl& fileUrl);
|
||||||
Q_INVOKABLE void upload(const QUrl& fileUrl, const QString& fileId, const QString& ticket);
|
Q_INVOKABLE void upload(const QUrl& fileUrl, const QString& fileId, const QString& ticket, const QString &fileName);
|
||||||
|
|
||||||
Q_INVOKABLE void download(QString fileId);
|
Q_INVOKABLE void download(QString fileId);
|
||||||
Q_INVOKABLE void pause(const QString& fileId);
|
Q_INVOKABLE void pause(const QString& fileId);
|
||||||
|
|
Loading…
Reference in New Issue