UploadedFile already holds the whole attachment in memory; getvalue()
made a second full copy of each of the 230 files before writing. Copy
through the file interface instead. Smoke tests pin the progress
callback contract: once per XML file, including unreadable ones.
Refs #1
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>