From d6d19795b287957b33940fa990503801319a3650 Mon Sep 17 00:00:00 2001 From: Hanif Koh Date: Mon, 28 Sep 2026 15:54:48 +0800 Subject: [PATCH] Keep Downloads on an Unused Name Until They Complete When the server supplied the name, the download marker stayed under the URL-derived name, so the adopted name was not reserved against other downloads. The final rename also replaced any file that took the name while the download ran. Move the marker to the adopted name before any data is written, and check the name again right before the final rename, picking the next free name if it is taken by then. --- src/slic3r/GUI/DownloaderFileGet.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/slic3r/GUI/DownloaderFileGet.cpp b/src/slic3r/GUI/DownloaderFileGet.cpp index b31aa29b4a..4a7269affa 100644 --- a/src/slic3r/GUI/DownloaderFileGet.cpp +++ b/src/slic3r/GUI/DownloaderFileGet.cpp @@ -213,6 +213,20 @@ void FileGet::priv::get_perform() } catch (const boost::filesystem::filesystem_error&) { unused.clear(); } + const boost::filesystem::path tmp_path = unused.empty() ? m_tmp_path : download_marker_path(m_dest_folder, unused); + if (tmp_path != m_tmp_path) { + // Move the marker to the adopted name so that other downloads see the name as taken. + // Only before anything is written, so that no downloaded data has to be carried over. + FILE* tmp_file = m_written == 0 ? fopen(wxString(tmp_path.wstring()).c_str(), "wb") : nullptr; + if (tmp_file != nullptr) { + fclose(file); + boost::system::error_code ec; + boost::filesystem::remove(m_tmp_path, ec); + file = tmp_file; + m_tmp_path = tmp_path; + } else + unused.clear(); + } if (!unused.empty()) m_filename = unused; dest_path = m_dest_folder / m_filename; @@ -320,6 +334,18 @@ void FileGet::priv::get_perform() m_evt_handler->QueueEvent(evt); } fclose(file); + // Another file may have taken the name while downloading. + if (!dest_path.empty() && boost::filesystem::exists(dest_path)) { + std::string unused; + if (!find_unused_filename(m_dest_folder, m_filename, m_tmp_path, unused)) + throw std::runtime_error("No unused file name."); + m_filename = unused; + dest_path = m_dest_folder / m_filename; + wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_NAME_CHANGE); + evt->SetString(boost::nowide::widen(m_filename)); + evt->SetInt(m_id); + m_evt_handler->QueueEvent(evt); + } boost::filesystem::rename(m_tmp_path, dest_path); } catch (const std::exception& /*e*/)