Reported and root-caused by @needo37. Importing a model via the MakerWorld
URL-download feature into a writable external folder (e.g. SMB/NFS-mounted
NAS) saved the 3MF into Bambuddy's internal managed library dir, not the
external mount. The file card showed in the File Manager under the
external folder, but the bytes never landed on the NAS, and the on-disk
copy was UUID-renamed so a find by the original basename matched nothing.
Root cause was save_3mf_bytes_to_library at backend/app/api/routes/library.py:422:
it accepted folder_id but never loaded the folder, never inspected
is_external / external_path, hardcoded the destination to
get_library_files_dir() with a UUID name, and left the LibraryFile row
with is_external=False. So the row's folder_id pointed at the external
folder while its bytes and is_external flag both said "managed/internal".
Same class of bug as #1112, which had been fixed for the multipart-upload
and move paths but never applied to this byte-import path.
Fix mirrors the multipart-upload path directly:
- Load target_folder from folder_id when non-None.
- Feed it to _resolve_upload_destination(target_folder, filename), which
already returns (dest, is_external) and enforces the 403-read-only /
400-unwritable-or-missing / 409-collision rejections.
- Write bytes to dest (real filename for external, UUID for managed).
- Persist the row with file_path=_stored_file_path(dest, is_external)
and is_external=is_external.
The route-layer read-only guard at makerworld.py:256-260 is preserved -
it returns the friendlier error before the upstream download burns
bandwidth - and _resolve_upload_destination's identical check stays as
defence-in-depth for any future caller that skips the route gate.
Thumbnails continue to live under the managed get_library_thumbnails_dir()
regardless of the 3MF's location, matching the upload path.