实现断点续传,待测试
parent
f85d98082e
commit
e7f809a973
|
@ -112,6 +112,9 @@ Popup {
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
console.log("pause")
|
console.log("pause")
|
||||||
FileTransferManager.pause(fileId)
|
FileTransferManager.pause(fileId)
|
||||||
|
} else {
|
||||||
|
FileTransferManager.download(fileId,
|
||||||
|
name, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,7 +278,7 @@ curl_off_t getHttpFileSize(const std::string &url)
|
||||||
curl_off_t fileLength = 0;
|
curl_off_t fileLength = 0;
|
||||||
|
|
||||||
CURL *handle = initCurlWithCommonOptions();
|
CURL *handle = initCurlWithCommonOptions();
|
||||||
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
|
curl_easy_setopt(handle, CURLOPT_URL, (baseUrl + url).c_str());
|
||||||
curl_easy_setopt(handle, CURLOPT_HEADER, 0); //只需要header头
|
curl_easy_setopt(handle, CURLOPT_HEADER, 0); //只需要header头
|
||||||
curl_easy_setopt(handle, CURLOPT_NOBODY, 1); //不需要body
|
curl_easy_setopt(handle, CURLOPT_NOBODY, 1); //不需要body
|
||||||
|
|
||||||
|
@ -292,14 +292,8 @@ curl_off_t getHttpFileSize(const std::string &url)
|
||||||
return fileLength;
|
return fileLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool httpDownload(const std::string &url, const FileItem &item)
|
bool httpDownload(const std::string &url, const std::string &savePath, const FileItem &item)
|
||||||
{
|
{
|
||||||
auto fileSize = getHttpFileSize(url);//获得文件大小。
|
|
||||||
if (fileSize == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
qDebug() << "FileSize: " << fileSize;
|
|
||||||
|
|
||||||
downloadingMapMutex.lock();
|
downloadingMapMutex.lock();
|
||||||
auto [iter, _] = downloadingMap.emplace(item.id, (FileDownloading) item);
|
auto [iter, _] = downloadingMap.emplace(item.id, (FileDownloading) item);
|
||||||
downloadingMapMutex.unlock();
|
downloadingMapMutex.unlock();
|
||||||
|
@ -309,8 +303,8 @@ bool httpDownload(const std::string &url, const FileItem &item)
|
||||||
obj.curlHandle = initCurlWithCommonOptions();
|
obj.curlHandle = initCurlWithCommonOptions();
|
||||||
if (!obj.curlHandle)
|
if (!obj.curlHandle)
|
||||||
return false;
|
return false;
|
||||||
obj.totalSize = fileSize;//原始文件大小
|
obj.totalSize = item.totalSize;//原始文件大小
|
||||||
obj.file = std::ofstream("D:\\Downloads\\" + obj.name.toStdString() + ".zip", std::ios::binary);
|
obj.file = std::ofstream(savePath, std::ios::binary | std::ios::app);
|
||||||
|
|
||||||
if (!obj.file.is_open()) {
|
if (!obj.file.is_open()) {
|
||||||
qDebug() << "Open File Failed";
|
qDebug() << "Open File Failed";
|
||||||
|
@ -320,7 +314,7 @@ bool httpDownload(const std::string &url, const FileItem &item)
|
||||||
|
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_HEADER, 0);
|
curl_easy_setopt(obj.curlHandle, CURLOPT_HEADER, 0);
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_NOSIGNAL, 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_URL, (baseUrl + url).c_str());
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_WRITEDATA, (void *) &obj);
|
curl_easy_setopt(obj.curlHandle, CURLOPT_WRITEDATA, (void *) &obj);
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_WRITEFUNCTION, writeDataFunc);
|
curl_easy_setopt(obj.curlHandle, CURLOPT_WRITEFUNCTION, writeDataFunc);
|
||||||
curl_easy_setopt(obj.curlHandle, CURLOPT_NOPROGRESS, false);//设为false 下面才能设置进度响应函数
|
curl_easy_setopt(obj.curlHandle, CURLOPT_NOPROGRESS, false);//设为false 下面才能设置进度响应函数
|
||||||
|
@ -339,42 +333,36 @@ bool httpDownload(const std::string &url, const FileItem &item)
|
||||||
return res == CURLE_OK;
|
return res == CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileTransferManager::download(const QString& fileId)
|
void FileTransferManager::download(const QString &fileId, const QString &fileName, bool resume)
|
||||||
{
|
{
|
||||||
QtConcurrent::run([fileId, this] {
|
QtConcurrent::run([fileId, fileName, resume, this] {
|
||||||
qDebug() << "Start Get";
|
qDebug() << "Start Get";
|
||||||
|
|
||||||
std::string resData;
|
std::string resData;
|
||||||
if (CURLE_OK != httpGet("File/" + fileId.toStdString() + "/status", resData))
|
if (CURLE_OK != httpGet("File/" + fileId.toStdString() + "/status", resData))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << resData.c_str();
|
qDebug() << resData.c_str();
|
||||||
auto resJson = QJsonDocument::fromJson(resData.c_str());
|
auto resJson = QJsonDocument::fromJson(resData.c_str());
|
||||||
//if(!resJson["isCompleted"].toBool())
|
if (!resJson["isCompleted"].toBool()) {
|
||||||
|
qDebug() << "File Not Completed";
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size = resJson["size"].toInteger();
|
||||||
|
std::string savePath = "D:\\Downloads\\" + fileName.toStdString();
|
||||||
/* int size = resJson["size"].toInt();
|
QFileInfo fileInfo(savePath.c_str());
|
||||||
FileItem item{fileId, resJson["md5"].toString(), 0, size};
|
int64_t completedSize = fileInfo.exists() ? fileInfo.size() : 0;
|
||||||
QTimer::singleShot(0, qApp, [this, item]() {
|
FileItem item{true, fileId, fileName, completedSize, size};
|
||||||
|
if (!resume)
|
||||||
|
QTimer::singleShot(0, qApp, [item]() {
|
||||||
FileTransferListModel::instance().insertItem(item);
|
FileTransferListModel::instance().insertItem(item);
|
||||||
});*/
|
});
|
||||||
|
|
||||||
auto fileUrl = "File/" + fileId.toStdString();
|
|
||||||
|
|
||||||
|
|
||||||
/* curl_slist *headers = nullptr;
|
|
||||||
headers = curl_slist_append(headers, "Range: bytes=0-");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);*/
|
|
||||||
|
|
||||||
|
|
||||||
int64_t size = getHttpFileSize(fileUrl);
|
|
||||||
FileItem item{true, fileId, fileId, 0, size};
|
|
||||||
|
|
||||||
auto res = httpDownload(fileUrl, item);
|
|
||||||
|
|
||||||
|
|
||||||
|
auto fileUrl = std::format("File/{}?rangeStart={}&rangeEnd={}", fileId.toStdString(), completedSize, size);
|
||||||
|
auto res = httpDownload(fileUrl, savePath, item);
|
||||||
|
/*auto fileUrl = std::format("File/{}?rangeStart={}&rangeEnd={}", fileId.toStdString(), 0, size / 2);
|
||||||
|
auto res = httpDownload(fileUrl, savePath, item);
|
||||||
|
fileUrl = std::format("File/{}?rangeStart={}&rangeEnd={}", fileId.toStdString(), size / 2, size);
|
||||||
|
res = httpDownload(fileUrl, savePath, item);*/
|
||||||
qDebug() << "End Get" << res;
|
qDebug() << "End Get" << res;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -410,52 +398,6 @@ int64_t FileTransferManager::getFileSize(const QUrl &fileUrl)
|
||||||
return QFile(fileUrl.toLocalFile()).size();
|
return QFile(fileUrl.toLocalFile()).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileTransferManager::resume(const QString &fileId)
|
|
||||||
{
|
|
||||||
|
|
||||||
QtConcurrent::run([fileId, this] {
|
|
||||||
qDebug() << "Start Get";
|
|
||||||
|
|
||||||
std::string resData;
|
|
||||||
if (CURLE_OK != httpGet("File/" + fileId.toStdString() + "/status", resData))
|
|
||||||
return;
|
|
||||||
|
|
||||||
qDebug() << resData.c_str();
|
|
||||||
return;
|
|
||||||
auto resJson = QJsonDocument::fromJson(resData.c_str());
|
|
||||||
//if(!resJson["isCompleted"].toBool())
|
|
||||||
// return;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* int size = resJson["size"].toInt();
|
|
||||||
FileItem item{fileId, resJson["md5"].toString(), 0, size};
|
|
||||||
QTimer::singleShot(0, qApp, [this, item]() {
|
|
||||||
FileTransferListModel::instance().insertItem(item);
|
|
||||||
});*/
|
|
||||||
|
|
||||||
auto fileUrl = "https://curl.se/download/curl-8.1.2.zip";
|
|
||||||
|
|
||||||
|
|
||||||
/* curl_slist *headers = nullptr;
|
|
||||||
headers = curl_slist_append(headers, "Range: bytes=0-");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);*/
|
|
||||||
|
|
||||||
|
|
||||||
int64_t size = getHttpFileSize(fileUrl);
|
|
||||||
FileItem item{true, fileId, fileId, 0, size};
|
|
||||||
QTimer::singleShot(0, qApp, [this, item]() {
|
|
||||||
FileTransferListModel::instance().insertItem(item);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto res = httpDownload(fileUrl, item);
|
|
||||||
|
|
||||||
|
|
||||||
qDebug() << "End Get" << res;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FileTransferManager::getFileName(const QUrl &fileUrl)
|
QString FileTransferManager::getFileName(const QUrl &fileUrl)
|
||||||
{
|
{
|
||||||
return fileUrl.fileName();
|
return fileUrl.fileName();
|
||||||
|
|
|
@ -24,9 +24,8 @@ public:
|
||||||
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, const QString &fileName);
|
Q_INVOKABLE void upload(const QUrl& fileUrl, const QString& fileId, const QString& ticket, const QString &fileName);
|
||||||
|
|
||||||
Q_INVOKABLE void download(const QString& fileId);
|
Q_INVOKABLE void download(const QString& fileId, const QString& fileName, bool resume = false);
|
||||||
Q_INVOKABLE void pause(const QString& fileId);
|
Q_INVOKABLE void pause(const QString& fileId);
|
||||||
Q_INVOKABLE void resume(const QString& fileId);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue