How to test file upload: a complete checklist

A test plan for upload forms and endpoints, with the right sample file for every case.

Published by SampleTestFiles. About 4 minutes to read.

A file upload looks like one feature and behaves like six. The browser picks the file, the network carries it, a proxy may buffer it, the server validates it, storage keeps it and something later reads it back. A bug can sit in any of those places. This guide is a test plan that covers them in order, starting with the cases that fail most often.

Before you start

Write down the rules the upload is supposed to enforce. You cannot test a limit nobody has stated. At minimum you need:

  • the accepted file types
  • the maximum size, and whether there is a minimum
  • how many files can be sent at once
  • what the user should see when a rule is broken

If those rules are not documented, finding them out is the first result of your testing.

1. The happy path

Upload the smallest valid file of each accepted type. A 1 KB text file or a 10 KB PDF is enough. Then check more than the success message:

  • The file appears where the product says it will.
  • Downloading it returns the same bytes. Compare SHA-256 checksums with the value on the sample's download page.
  • The stored name, size and type are correct.

If the application offers both a file picker and drag-and-drop, repeat the test with each. They are separate code paths in most front ends.

2. Size limits

Test on both sides of every limit. For a 5 MB limit, upload the 1 MB file, which must succeed, and the 10 MB file, which must fail. Then try the 5 MB file itself to learn how the boundary is treated.

Two details catch people out:

  • A request is bigger than the file inside it. A multipart form adds a boundary and headers, usually a few hundred bytes. A limit on the request body is therefore reached slightly before the file reaches the same number.
  • There is more than one limit. A CDN, a reverse proxy, the web server, the framework and the application can each refuse a request. The lowest limit wins, and its error page may be nothing like your application's.

The guide to testing file size limits lists the defaults of common servers and frameworks.

Do not forget the lower bound. Upload the zero-byte file. An empty upload should be refused with a message, or accepted on purpose. It should never produce a server error or a record that points at nothing.

3. File types

Upload one file of a type that is not allowed and check the message. Then test whether validation looks at content or only at the name:

  1. Take a PNG sample and rename it so that it ends in .pdf.
  2. Upload it to a form that accepts PDF only.

If it is accepted, the server is trusting the file name. Do the reverse as well: a genuine PDF with a .png extension. See how to test MIME types for the full method.

Pay attention to formats that are easy to misidentify. DOCX, XLSX and PPTX files are ZIP archives and are often detected as application/zip. A file with no extension has only its content to go on.

4. File names

File names travel through URL encoding, HTTP headers, file systems and databases, and each can mangle them. Upload:

After each upload, download the file again and look at the name the browser saves. Broken Content-Disposition headers show up here as underscores, question marks or truncated names. For the duplicate case, confirm that the second file did not silently replace the first unless that is the documented behaviour.

5. Interruptions

Use a file large enough to take several seconds, such as the 10 MB binary sample, and throttle the connection in your browser's developer tools if you need to.

  • Cancel the upload midway. No partial file should be listed afterwards.
  • Disconnect the network midway. The user should see an error and be able to retry.
  • Close the tab midway, reopen the page and check for orphaned or half-complete records.
  • Submit the form twice in quick succession. You should not end up with two copies.

6. Security checks

These are not a substitute for a security review, but they find the common mistakes quickly.

  • Active content. Upload an HTML sample and an SVG sample, then open the stored file's URL directly. It should download, or be served from a separate domain, rather than render as a page on your site.
  • Response headers. Stored files should be served with X-Content-Type-Options: nosniff and a Content-Type that matches what was validated.
  • Path handling. The stored location must not be derived from the user's file name. Check that a name containing ../ is neutralised.
  • Archives. If the product unpacks ZIP files, confirm that it limits the number of entries and the total extracted size.

7. A quick command-line check

You can exercise an endpoint without a browser. This sends a file as multipart form data and prints the status code:

curl -sS -o /dev/null -w '%{http_code}\n' \
  -F 'file=@sample-pdf-1mb.pdf;type=application/pdf' \
  https://your-app.example/upload

Swap in larger files until the status changes from 200 or 201 to 413. That tells you where the real limit is, whatever the documentation says.

What to record

For each test, note the file name, its size in bytes and its SHA-256 checksum, the expected result and the actual result. With exact inputs written down, a developer can reproduce any failure in minutes.

Files used in this guide

Sample files referred to in this guide
FileFormatSizeContentsDownload
1 KB TXT samplesample-txt-1kb.txt TXT 1 KB1,024 bytes Numbered lines: 8 Download TXT
1 MB PDF samplesample-pdf-1mb.pdf PDF 1 MB1,048,576 bytes Pages: 10 Download PDF
5 MB JPG samplesample-jpg-5mb.jpg JPG 5 MB5,242,880 bytes 4,568 × 3,426 px Download JPG
10 MB BIN samplesample-bin-10mb.bin BIN 10 MB10,485,760 bytes Pseudo-random bytes Download BIN
Empty file (0 bytes)empty-file.txt TXT 0 B0 bytes Lines: 0 Download TXT
File name with non-ASCII characterssample-ünïcödé-文件-имя.txt TXT 75 B75 bytes File name scripts: Latin with diacritics, Han, Cyrillic Download TXT
File name with spacessample file name with spaces.txt TXT 34 B34 bytes File name length: 32 characters Download TXT

Related guides