How to test file downloads

Completeness, integrity, speed, range requests and resume, each with a command you can run.

Published by SampleTestFiles. About 4 minutes to read.

A download is working when four things are true: every byte arrives, no byte is changed, it arrives in reasonable time, and a broken connection can be recovered from. Each can be tested with a file whose size and checksum you know beforehand. Every sample on this site publishes both.

1. Is the file complete?

Compare sizes. Download a sample and print its byte count:

curl -sS -O https://your-cdn.example/sample-bin-10mb.bin
wc -c < sample-bin-10mb.bin

A 10 MB sample must report exactly 10485760. A smaller number means the transfer stopped early; a different number altogether usually means something rewrote the content.

You can ask the server what it intends to send without downloading anything:

curl -sSI https://your-cdn.example/sample-bin-10mb.bin

Look for Content-Length: 10485760 in the response. If the header is missing, the server is streaming with chunked encoding, and clients cannot show accurate progress.

2. Is the file unmodified?

Size alone does not prove integrity. Compute a SHA-256 checksum and compare it with the value on the sample's download page.

sha256sum sample-bin-10mb.bin        # Linux
shasum -a 256 sample-bin-10mb.bin    # macOS

On Windows, in PowerShell:

Get-FileHash .\sample-bin-10mb.bin -Algorithm SHA256

A mismatch with a correct size points to content being altered in transit. The usual culprits are proxies that rewrite text, and line-ending conversion when a text file passes through a tool running in text mode.

3. The compression trap

Servers and CDNs compress text responses. That is good for users and misleading for testers, in two ways.

First, speed measurements taken with a text file are inflated. A 10 MB text file may travel as 2 MB. Use a BIN sample, whose random bytes cannot be compressed, whenever you are measuring the network.

Second, a file that is already gzip-compressed can be mangled by a misconfigured server. If a .gz file is sent with Content-Encoding: gzip, the client decompresses it automatically and saves decompressed content under a .gz name. To see what a server really sends, request without accepting any encoding and inspect the headers:

curl -sS -D - -o /dev/null -H 'Accept-Encoding: identity' \
  https://your-cdn.example/sample-gz-1mb.gz

A correctly configured server answers with Content-Type: application/gzip and no Content-Encoding header.

4. How fast is it?

curl can report transfer statistics. This discards the body and prints the status, size, average speed and total time:

curl -sS -o /dev/null \
  -w '%{http_code}  %{size_download} bytes  %{speed_download} B/s  %{time_total} s\n' \
  https://your-cdn.example/sample-bin-10mb.bin

For a fair measurement:

  • Use an incompressible file large enough to run for several seconds.
  • Run the command at least five times and take the median.
  • Treat the first request separately. It may be a cache miss at the CDN, which is worth measuring in its own right.
  • Add %{time_starttransfer} to see the time to first byte, which separates server delay from transfer time.

5. Range requests

Range requests let a client ask for part of a file. Video seeking, resumable downloads and parallel download managers all depend on them. Ask for the first 1,024 bytes:

curl -sS -D - -o part.bin -r 0-1023 \
  https://your-cdn.example/sample-mp4-10mb.mp4

A server that supports ranges replies with:

  • status 206 Partial Content
  • Content-Range: bytes 0-1023/10485760
  • Content-Length: 1024

If it answers 200 OK with the whole file, ranges are not supported. In a browser the symptom is a video that plays from the start but cannot be dragged to a new position.

Also request a range that starts beyond the end of the file, for example -r 99999999-. The correct response is 416 Range Not Satisfiable.

6. Resuming

Interrupt a download with Ctrl+C partway through, then continue it:

curl -C - -O https://your-cdn.example/sample-bin-10mb.bin

The -C - option tells curl to look at the partial file and request only the remainder. When it finishes, verify the checksum. A resumed file with the right size and the wrong checksum means the server sent different content the second time, which happens when a file is replaced during the download and the client does not check ETag or Last-Modified.

7. Headers and file names

When a download is triggered from a web page, the response headers decide what the browser does.

  • Content-Disposition: attachment; filename="report.pdf" forces a download and suggests a name.
  • Content-Type should match the real type. With X-Content-Type-Options: nosniff, browsers will not guess.
  • Cache-Control and ETag determine whether repeat downloads are served from cache.

File names with spaces or non-ASCII characters need the extended filename*=UTF-8''... form. Test with the samples that have spaces and non-ASCII characters in their names, and check the name the browser actually saves.

8. In the browser

Finish with a manual pass in each browser you support, including one phone:

  1. Click the download link and confirm the file is saved with the expected name.
  2. Throttle the network in developer tools and confirm that progress is shown.
  3. Go offline during the download and confirm that the failure is visible and that retrying works.
  4. Download the same file twice and check whether the second request is answered from cache when it should be.

For automated browser checks, the Playwright guide shows how to capture a download and assert on its size.

Files used in this guide

Sample files referred to in this guide
FileFormatSizeContentsDownload
1 MB BIN samplesample-bin-1mb.bin BIN 1 MB1,048,576 bytes Pseudo-random bytes Download BIN
10 MB BIN samplesample-bin-10mb.bin BIN 10 MB10,485,760 bytes Pseudo-random bytes Download BIN
10 MB MP4 samplesample-mp4-10mb.mp4 MP4 10 MB10,485,760 bytes 640 × 360 px Download MP4
10 MB ZIP samplesample-zip-10mb.zip ZIP 10 MB10,485,760 bytes Entries: 4 Download ZIP
File name with spacessample file name with spaces.txt TXT 34 B34 bytes File name length: 32 characters Download TXT

Related guides