Ahosting Logo
Knowledge Base

How to Handle Video Uploads from a Web Application

The mistake that takes a site downThe upload arrivesand the request handler starts encodingThe request holds a worker for minuteswhile other visitors queue behind itA few uploads exhaust the pooland the whole site stops respondingAccept the file, put a job on a queue, return immediately, and encode in a worker process. Nothing else about videouploads matters as much.

Letting visitors upload video is different from processing your own files. The input is untrusted, the work is expensive, and it arrives at unpredictable times, and doing it inside the web request is the mistake that takes a site down.

Never process in the request

Encoding a video takes minutes. A web request that waits for it holds a PHP process the whole time, and several at once exhaust what the account allows, so the site becomes unavailable to everyone because two people uploaded a file.

The arrangement that works: accept the upload, record a job, return immediately, and process it separately: a queue consumed by a worker, or a cron job picking up pending work.

The user gets a "processing" state and a notification when it finishes. That is better for them as well, because a request that runs for four minutes fails on most connections anyway. How to Build a Batch Video Processing Pipeline goes into the worker side.

Validate before you trust anything

An uploaded file is a stranger's data, and the filename and extension are theirs to choose.

Inspect the file itself rather than believing the extension. ffprobe reads the header and tells you what is actually there, whether it has a video stream, whether the duration is sane, what codec it uses.

Three checks reject most bad input: no video stream, a duration of zero or something absurd, and dimensions outside what you accept. Doing them first turns a pipeline that dies halfway into one that skips a file and continues. Using ffprobe to Inspect Media Files explains the commands.

Never pass a user filename into a shell

The vulnerability specific to this job.

A filename is untrusted input. Building a command by concatenating it is the classic route to command injection, and a media pipeline is where it most often appears because the commands are long and get assembled as strings.

Rename every upload to something you generated: a random identifier, and keep the original name only as a label in your database. Then use your language's argument-array form in place of a shell string, so nothing is interpreted.

Store uploads outside the web root

Raw uploads should not sit anywhere the web server will serve, and certainly not anywhere it will execute.

A file that is not really a video, uploaded into a directory that runs PHP, is a compromised site. Placement is the control here; extension checks are not sufficient on their own. There is more in Understanding File Permissions and Ownership.

Serve the finished output from a separate location, and if the content is paid or private, through your application rather than directly. A predictable URL is a public URL.

Set limits, and set them in three places

An upload limit is not one setting.

The web server has a maximum request size. PHP has upload_max_filesize and post_max_size, which must both be raised because an upload arrives inside a form submission. And your application should enforce its own limit so the rejection is a message in place of a server error. For the PHP pair, see How to Configure PHP Settings in cPanel.

Raising only one produces the confusing case where the limit says 500 MB and a 200 MB file still fails.

For genuinely large files, a chunked upload, sending the file in pieces, avoids these limits entirely and survives a dropped connection, which a single large POST does not.

Cap the work, not just the file

A small file can be expensive: a short clip at high resolution and frame rate, or a deliberately awkward one, can occupy a core for far longer than its size suggests.

So limit duration and resolution as well as bytes, and put a timeout on the encode. A job with no timeout can run until something else fails.

Limit concurrency too. One encode at a time on a small server is a deliberate choice; several is how a VPS becomes unresponsive. Managing VPS Resources and Monitoring Performance sets out watching it.

Normalise the output

Uploads arrive in every format and configuration people's phones produce. Serving them as they came means some visitors cannot play some videos.

Convert everything to one delivery format: H.264 in MP4 with yuv420p, AAC audio, and the metadata cleaned up. That plays everywhere, and it makes your storage and bandwidth predictable.

Watch for two things phones produce: rotation flags, so a video that played upright arrives sideways, and variable frame rate, which is the usual cause of audio drifting out of sync. Both are visible in ffprobe before you encode.

Tell the user what happened

A job that failed silently looks identical to one still running.

Record a status per upload, queued, processing, ready, failed, and show it. When it fails, say whether it was the file or your side, because "unsupported format" and "try again later" lead the user to do different things.

Keep the failure reason in your own log with the ffprobe output. That is what makes a report actionable a week later. Troubleshooting Common FFmpeg Errors goes into reading it.

Clean up

Originals, failed jobs and abandoned uploads accumulate, and video accumulates quickly.

Decide whether you keep the source after encoding: useful if you re-encode later, expensive if you never do, and delete failed and abandoned uploads on a schedule.

Set a disk alert well before full. A pipeline that fills the disk stops the website too, and the errors will not mention video.

Uploaded files arrive carrying device models, timestamps and sometimes locations, and republishing them is accidental. How to Edit Metadata and Chapters with FFmpeg deals with stripping it in the same pass.

Files chosen by strangers are untrusted input handed to a complex decoder, and bounding what a bad one can do is a separate exercise. See How to Process Untrusted Video Uploads Safely.