A Score Upload Needs More Than an Accept Attribute
Disclosure: I’m Giang Pham, Pianory’s maker. AI helped draft this article from Pianory's source code. It describes the implementation and unit-test coverage, not production testing. A file picker can suggest which files a user should choose, but that suggestion is not an import contract. A browser may let someone select a misleading filename, a broken archive, or a file that has the right…
Defining an importer's input contract is crucial for a dependable file upload system. Pianory's MusicXML importer explicitly lists supported formats: MusicXML, compressed MusicXML, MIDI, and PDF. Early rejection steps check file size and extension before processing, distinguishing between filename guidance and actual content handling.
ZIP archives follow the archive path, regardless of filename extension. The importer treats audio archives as containers with manifest entries to select the correct score file. If no valid score is found, an archive error is returned. The unzip process expands entries for the current step and rejects entries exceeding 40 MB uncompressed size. Tests cover various scenarios like decoy files and malformed archives.
A parser should clearly declare the supported subset of MusicXML, rejecting empty input, entity declarations, timewise scores, and documents lacking a partwise score element. It allows a public DOCTYPE but rejects entity declarations. In a browser, it validates XML using DOMParser and checks for parser errors, preventing malformed XML issues later. This defines a supported format boundary but does not claim complete schema validation.
After parsing, Pianory extracts essential metadata like title, composer, part count, staves, measure count, and key from the MusicXML. If no title is present, the filename serves as a fallback. MIDI conversion uses the filename fallback for the title. The app encodes MusicXML as a versioned mxl1 value with base64-encoded gzip data, checking against a one-million-character limit.
The server validates the encoded string length and expected prefix and base64 shape but avoids decompressing and parsing the score again during sync pushes.
Validating each representation where it changes—file selection, raw bytes, archive entry, parsed document, and stored payload—is essential. Tests should target these handoffs with wrong extensions, decoy archive entries, hostile entity declarations, and oversized encoded content. This provides valuable insight into the importer's contracts without replacing a comprehensive production security review.
The hardest edge cases in an upload pipeline typically occur during the transition from filename to bytes, archive to document, or document to stored data.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.