Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring file uploads: discard the supplied filename before writing

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A multipart original filename is caller-controlled metadata, not a safe path component.

Download Spring source kit

The test sends traversal text

The accepted fixture upload declares ../../outside.csv. The controller never joins that value to the storage directory. It calls Files.createTempFile within a JUnit temporary root, returns only the generated basename and verifies the bytes exist at that resolved path. The test proves one path boundary in local storage. It does not prove a mounted production volume's permissions, symlink policy or cleanup schedule.

Ignore content type as an authority signal too. A second test labels HTML bytes text/csv; header validation rejects it before a file is created. A filename extension and a MIME declaration can both be chosen by the uploader. The format lesson describes the deliberately narrow byte check; the entrypoint stages only accepted bytes.

Separate public labels from storage keys

If users need to see their original filename, store a sanitized display label in a separate field with length and character bounds. Do not let it determine filesystem placement. Generate an opaque key for storage and keep an ownership record. On failure after creating a temporary file, delete it or mark it for cleanup; the fixture deletes its file on a write error but does not simulate disk failure.

Checked source

Java
Path stored = Files.createTempFile(storage, "receipt-import-", ".csv");
try { Files.write(stored, content); }
catch (IOException failure) {
    Files.deleteIfExists(stored);
    throw failure;
}

Verification boundary

MultipartReceiptImportTest.storesValidatedBytesUnderGeneratedName and MultipartReceiptImportTest.rejectsFakeCsvMediaTypeWhenBytesHaveWrongHeader in the downloadable Spring source kit. The excerpt is shortened; the kit contains the complete test.

Costs and limits

The path test runs in a temporary directory and uses a generated local file. It does not audit filesystem ACLs, symbolic links, object-store policies, malware scanning or file retention. Staging bytes costs disk space and must have a quota outside this fixture.

Common Mistakes

  • Do not join getOriginalFilename() to a storage root.
  • Do not accept a file because its extension says CSV.
  • Do not expose an internal absolute path as the public upload identifier.

Read next

Spring MVC multipart receipt import: validate before storing, Spring CSV uploads: reject malformed UTF-8 and an unknown header, Spring MockMvc multipart tests: what the fixture proves.

spring
spring-boot
upload-generated-filename
Storage details