138{
140 assert(!
m_url.empty());
143
145
146
147 std::string extension;
149 {
150 std::string final_filename;
151 bool found = false;
152 try {
154 } catch (const boost::filesystem::filesystem_error& e)
155 {
156 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
157 evt->SetString(e.what());
160 return;
161 }
162 if (!found) {
163 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
167 return;
168 }
169
171 extension = boost::filesystem::path(
m_filename).extension().string();
172
174
175 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_NAME_CHANGE);
176 evt->SetString(boost::nowide::widen(
m_filename));
179 }
180
181 boost::filesystem::path dest_path;
182 if(!extension.empty())
184
185 wxString temp_path_wstring(
m_tmp_path.wstring());
186
187
188
189
191
192 FILE* file;
193
195 file = fopen(temp_path_wstring.c_str(), "wb");
196 else
197 file = fopen(temp_path_wstring.c_str(), "ab");
198
199
200 if (file == NULL) {
201 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
202
206 return;
207 }
208
209 std:: string range_string = std::to_string(
m_written) +
"-";
210
212 size_t written_this_session = 0;
217 if(dest_path.empty()) {
219 if (!filename.empty()) {
220
221
223 std::string unused;
224 try {
226 unused.clear();
227 } catch (const boost::filesystem::filesystem_error&) {
228 unused.clear();
229 }
232
233
234 FILE* tmp_file =
m_written == 0 ? fopen(wxString(tmp_path.wstring()).c_str(),
"wb") : nullptr;
235 if (tmp_file != nullptr) {
236 fclose(file);
237 boost::system::error_code ec;
239 file = tmp_file;
241 } else
242 unused.clear();
243 }
244 if (!unused.empty())
247 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_NAME_CHANGE);
248 evt->SetString(boost::nowide::widen(
m_filename));
251 }
252 }
253 })
254 .on_progress([&](Http::Progress progress,
bool&
cancel) {
255
258 return;
259 }
262 fclose(file);
263
267 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_CANCELED);
270 return;
271
272 }
275 fclose(file);
279 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_PAUSED);
282 return;
283 }
284
287 }
288
289 if (progress.dlnow != 0) {
291 try
292 {
293 std::string part_for_write = progress.buffer.substr(written_this_session, progress.dlnow);
294 fwrite(part_for_write.c_str(), 1, part_for_write.size(), file);
295 }
296 catch (const std::exception& e)
297 {
298
299 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
300 evt->SetString(e.what());
304 return;
305 }
306 written_this_session = progress.dlnow;
307 m_written = written_previously + written_this_session;
308 }
309 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_PROGRESS);
311 evt->SetString(std::to_string(percent_total));
314 }
315
316 })
317 .on_error([&](std::string body, std::string error, unsigned http_status) {
318 if (file != NULL)
319 fclose(file);
320 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
321 if (!error.empty())
323 else
327 })
328 .on_complete([&](std::string body, unsigned ) {
329
330
331
332
333
334
335
336 try
337 {
338
340 {
341
342 std::string part_for_write = body.substr(
m_written);
343 fwrite(part_for_write.c_str(), 1, part_for_write.size(), file);
344
345 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_PROGRESS);
346 evt->SetString(std::to_string(100));
349 }
350 fclose(file);
351
352 if (!dest_path.empty() && boost::filesystem::exists(dest_path)) {
353 std::string unused;
355 throw std::runtime_error("No unused file name.");
358 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_NAME_CHANGE);
359 evt->SetString(boost::nowide::widen(
m_filename));
362 }
363 boost::filesystem::rename(
m_tmp_path, dest_path);
364 }
365 catch (const std::exception& )
366 {
367
368
369 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
370 evt->SetString(
_L(
"Failed to write and move."));
373 return;
374 }
375
376 wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_COMPLETE);
377 evt->SetString(dest_path.wstring());
380 })
381 .perform_sync();
382
383}
#define _L(s)
Definition OBJ.cpp:34
void cancel()
Definition DownloaderFileGet.cpp:415
Http & size_limit(size_t sizeLimit)
Definition Http.cpp:576
Http & on_header_callback(HeaderCallbackFn fn)
Definition Http.cpp:788
Http & set_range(const std::string &range)
Definition Http.cpp:582
static Http get(std::string url)
Definition Http.cpp:886
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:22
const size_t DOWNLOAD_MAX_CHUNK_SIZE
Definition DownloaderFileGet.cpp:34
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
wxString from_u8(const std::string &str)
Definition GUI.cpp:544
std::string extract_remote_filename(const std::string &str)
Definition DownloaderFileGet.cpp:128
const size_t DOWNLOAD_SIZE_LIMIT
Definition DownloaderFileGet.cpp:35
bool find_unused_filename(const boost::filesystem::path &dest_folder, const std::string &filename, const boost::filesystem::path &ignored_marker, std::string &result)
Definition utils.cpp:1494
std::string sanitize_file_basename(const std::string &name)
Definition Utils.hpp:326
boost::filesystem::path download_marker_path(const boost::filesystem::path &dest_folder, const std::string &filename)
Definition utils.cpp:1489
std::atomic_bool m_cancel
Definition DownloaderFileGet.cpp:110
boost::filesystem::path m_tmp_path
Definition DownloaderFileGet.cpp:109
size_t m_absolute_size
Definition DownloaderFileGet.cpp:114
std::atomic_bool m_pause
Definition DownloaderFileGet.cpp:111
size_t m_written
Definition DownloaderFileGet.cpp:113
std::atomic_bool m_stopped
Definition DownloaderFileGet.cpp:112