Why Classic ASP Uploads Are Slow, and What Actually Helps

Five causes, four of which are not your server — and how to tell which one you have.

Measure before you tune

"The upload is slow" has at least five unrelated causes, and four of them are not the server. Find out which one you have before changing anything:

TestWhat it tells you
Upload the same file from the same machine twiceWildly different times mean the network, not your code
Compare a 1 MB and a 100 MB fileIf time scales linearly, you are bandwidth-bound — that is normal
Upload from the server to itselfRemoves the network entirely; slow here means server-side work
Watch the worker process memoryA spike the size of the file means you are buffering, not streaming
Time the gap after the bar hits 100%That gap is post-upload processing, not transfer

Most reported "slow uploads" turn out to be a visitor's asymmetric connection. A typical home line uploads at a fraction of its download speed — a 500 MB file over a 10 Mbit upstream takes about seven minutes no matter what your server does. When that is the answer, the fix is honest progress reporting, not tuning.

The one server-side mistake that matters

Everything else on this page is a rounding error next to this: Request.BinaryRead pulls the entire request body into memory before your script runs, and parsing it allocates again.

binData = Request.BinaryRead(Request.TotalBytes)   ' the whole file, in RAM

Under concurrency this is what actually kills throughput. Ten simultaneous 200 MB uploads is 2 GB of allocation before anything is saved; the pool hits its memory recycle limit and drops every request in flight, including the ones that were fine.

Reading the body incrementally, or chunking it, keeps peak memory at one buffer regardless of file size, so throughput stays flat as concurrency rises instead of collapsing at a threshold. See chunked and resumable upload.

Disk

  • Do not cross a volume boundary at the end. Moving a file within one volume is a metadata update; moving it across volumes copies every byte. Put the temp folder and the destination on the same drive and MoveTo becomes instant.
  • Do not write across the network on the hot path. Write locally, replicate afterwards — see uploading to a network share.
  • Watch folder sizes. NTFS directory enumeration degrades once a folder holds hundreds of thousands of entries. Shard by date.
  • Exclude the upload folders from real-time antivirus scanning, or every write waits for a scan. Scan on a schedule instead.

Post-upload work

The gap between "bar full" and "page responds" is work you are doing after the transfer: a database insert, a virus scan, image processing, a notification email. Users read that gap as a hang.

  • Do the minimum synchronously — record the file and return.
  • Push slow work to a queue or a scheduled task.
  • If it must be synchronous, say so on screen. UploadProcessingMsg exists for exactly this moment.
uploader.UploadProcessingMsg = "Uploaded. Processing on the server, nearly done..."

Client-side wins

The fastest upload is the one you do not make:

  • Resize images in the browser. A phone photo is often 5 MB and needed at 200 KB. That is a 25× reduction before anything is sent — no server tuning comes close. See the image upload guide.
  • Reject early. A file that violates your size or type rules should never leave the machine. MaxSizeKB and AllowedFileExtensions are enforced in the browser.
  • Start on selection, not on submit. Uploading while the user fills in the rest of the form hides the transfer time completely.

IIS and infrastructure

SettingWhy it matters
App pool idle time-outSet to 0 — a recycle mid-transfer looks like a hang
Server.ScriptTimeoutToo low and long uploads die at a fixed elapsed time
uploadReadAheadSizeCan cause stalls over HTTPS or behind some modules
HTTPSModest CPU cost, and worth it regardless; on modern hardware it is not your bottleneck
CDN or proxyAdds a hop, and imposes its own body-size limit

A note on CDNs: they accelerate downloads, not uploads. Traffic still has to reach your origin, and the extra hop can make uploads marginally slower while adding a request-size cap. That is not an argument against using one — just do not expect it to speed uploads up.

What to do, in order

  1. Confirm it is not simply the visitor's upstream bandwidth.
  2. Stop buffering whole files — this is the big one.
  3. Resize and reject on the client.
  4. Keep temp and destination on the same volume.
  5. Move post-upload work off the request.
  6. Exclude upload folders from real-time scanning.
  7. Set the idle time-out to 0 and raise the script timeout.

Frequently asked questions

Why are my Classic ASP uploads slow?

Usually the visitor's upstream bandwidth. Server-side, the common cause is buffering the whole file in memory, which collapses under concurrency.

Does chunking make uploads faster?

Not for a single file — slightly slower, from per-request overhead. It makes them far faster under load, because memory stays flat.

Why does the progress bar reach 100% and then pause?

That pause is post-upload work on the server. Move it off the request, or tell the user it is happening.

Skip the plumbing

ASP Uploader does everything on this page out of the box: multi-file selection, a real progress bar, client and server validation, incremental large-file handling, and no COM component to register. Drop the folder on your server and add one include line.

Download the free trial Try the live demo Pricing