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+
1523namespace {
1624size_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+ }
0 commit comments