Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit ae8be75

Browse files
authored
Merge pull request #1314 from janhq/j/fix-resume-download
fix: resume download failed
2 parents d2904ee + b88b1bd commit ae8be75

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

engine/services/download_service.cc

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
#include "utils/format_utils.h"
1313
#include "utils/logging_utils.h"
1414

15+
#ifdef _WIN32
16+
#define ftell64(f) _ftelli64(f)
17+
#define fseek64(f, o, w) _fseeki64(f, o, w)
18+
#else
19+
#define ftell64(f) ftello(f)
20+
#define fseek64(f, o, w) fseeko(f, o, w)
21+
#endif
22+
1523
namespace {
1624
size_t WriteCallback(void* ptr, size_t size, size_t nmemb, FILE* stream) {
1725
size_t written = fwrite(ptr, size, nmemb, stream);
@@ -37,12 +45,19 @@ void DownloadService::AddDownloadTask(
3745
}
3846

3947
// all items are valid, start downloading
48+
bool download_successfully = true;
4049
for (const auto& item : task.items) {
4150
CLI_LOG("Start downloading: " + item.localPath.filename().string());
42-
Download(task.id, item, true);
51+
try {
52+
Download(task.id, item, true);
53+
} catch (const std::runtime_error& e) {
54+
CTL_ERR("Failed to download: " << item.downloadUrl << " - " << e.what());
55+
download_successfully = false;
56+
break;
57+
}
4358
}
4459

45-
if (callback.has_value()) {
60+
if (download_successfully && callback.has_value()) {
4661
callback.value()(task);
4762
}
4863
}
@@ -102,10 +117,15 @@ void DownloadService::Download(const std::string& download_id,
102117
std::string mode = "wb";
103118
if (allow_resume && std::filesystem::exists(download_item.localPath) &&
104119
download_item.bytes.has_value()) {
105-
FILE* existing_file = fopen(download_item.localPath.string().c_str(), "r");
106-
fseek(existing_file, 0, SEEK_END);
107-
curl_off_t existing_file_size = ftell(existing_file);
108-
fclose(existing_file);
120+
curl_off_t existing_file_size = GetLocalFileSize(download_item.localPath);
121+
if (existing_file_size == -1) {
122+
CLI_LOG("Cannot get file size: " << download_item.localPath.string()
123+
<< " . Start download over!");
124+
return;
125+
}
126+
CTL_INF("Existing file size: " << download_item.downloadUrl << " - "
127+
<< download_item.localPath.string() << " - "
128+
<< existing_file_size);
109129
auto missing_bytes = download_item.bytes.value() - existing_file_size;
110130
if (missing_bytes > 0) {
111131
CLI_LOG("Found unfinished download! Additional "
@@ -149,18 +169,40 @@ void DownloadService::Download(const std::string& download_id,
149169
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
150170

151171
if (mode == "ab") {
152-
fseek(file, 0, SEEK_END);
153-
curl_off_t local_file_size = ftell(file);
154-
curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, local_file_size);
172+
auto local_file_size = GetLocalFileSize(download_item.localPath);
173+
if (local_file_size != -1) {
174+
curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE,
175+
GetLocalFileSize(download_item.localPath));
176+
} else {
177+
CTL_ERR("Cannot get file size: " << download_item.localPath.string());
178+
}
155179
}
156180

157181
res = curl_easy_perform(curl);
158182

159183
if (res != CURLE_OK) {
160184
fprintf(stderr, "curl_easy_perform() failed: %s\n",
161185
curl_easy_strerror(res));
186+
throw std::runtime_error("Failed to download file " +
187+
download_item.localPath.filename().string());
162188
}
163189

164190
fclose(file);
165191
curl_easy_cleanup(curl);
166192
}
193+
194+
curl_off_t DownloadService::GetLocalFileSize(
195+
const std::filesystem::path& path) const {
196+
FILE* file = fopen(path.string().c_str(), "r");
197+
if (!file) {
198+
return -1;
199+
}
200+
201+
if (fseek64(file, 0, SEEK_END) != 0) {
202+
return -1;
203+
}
204+
205+
curl_off_t file_size = ftell64(file);
206+
fclose(file);
207+
return file_size;
208+
}

engine/services/download_service.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <curl/curl.h>
34
#include <filesystem>
45
#include <functional>
56
#include <optional>
@@ -73,4 +74,6 @@ class DownloadService {
7374
private:
7475
void Download(const std::string& download_id,
7576
const DownloadItem& download_item, bool allow_resume);
77+
78+
curl_off_t GetLocalFileSize(const std::filesystem::path& path) const;
7679
};

0 commit comments

Comments
 (0)