Image handling · v5.3
Pick a photo and it uploads immediately — no postback, no page reload, a thumbnail and a progress bar while it goes. The image is previewed, resized, rotated upright and optionally cropped in the browser, so a 6 MB phone photo arrives as a few hundred kilobytes.
v5.3 ships a content-aware image editor: focal-point smart-crop (edge-energy heuristic, no AI), draggable text and sticker overlays, brightness/contrast/saturation filter presets, an EXIF info panel, crop-ratio quick-pick chips, and AVIF/WebP output with a quality slider - plus EXIF auto-rotate on upload, PDF poster thumbnails, HEIC decode, and presets, all before a byte leaves the browser.
The smallest version that works
Two files. The control renders its own AJAX transport, so there is no UpdatePanel, no <form enctype> change and no handler to register — dropping the tag on the page is the whole client side:
<%@ Register Assembly="AjaxUploader" Namespace="AjaxUploader.Controls" TagPrefix="au" %>
<au:AjaxFileUpload ID="Uploader1" runat="server"
AllowMultiple="true"
AllowedFileExtensions=".jpg,.jpeg,.png,.gif,.webp"
ShowThumbnails="true"
ImageResize="true" ResizeMaxWidth="1600" ResizeMaxHeight="1600"
AutoOrient="true"
OnFileUploaded="Uploader1_FileUploaded" />
The upload has already finished by the time your code runs. The file is held under a GUID, and you decide where it lands:
protected void Uploader1_FileUploaded(object sender, FileUploadedEventArgs e)
{
var destination = Server.MapPath("~/uploads/" + e.FileName);
new UploadService().CopyFile(e.FileGuid, destination);
// e.FileName, e.FileSize, e.ContentType and e.RelativePath
// describe what just arrived - use MoveFile instead of CopyFile
// if you do not want the temporary copy kept.
}
That is a working AJAX image upload: multi-select, per-file thumbnails, a progress bar, browser-side downscaling and upright photos. Everything below is refinement on top of it.
Why AJAX matters more for images than for other files
A classic <asp:FileUpload> posts the whole form back. For images that is the worst case on both ends: the user stares at a frozen page with no progress while several megabytes of camera-roll JPEG travel, and the page they were filling in is thrown away and rebuilt on return.
Uploading over AJAX changes three things that only matter once files are large:
- The page survives. No postback, so form state, scroll position and anything else the user typed stay exactly where they were.
- Progress is real. The transfer is a request you can observe, so a per-file progress bar reflects bytes actually sent rather than a spinner.
- The bytes shrink first. Because the file is read in the browser before it is sent, it can be downscaled and re-encoded on the way out — which a form post cannot do at all.
That last one is the big one. A 6 MB photo bounded to 1600 px is usually 200-400 KB, so it never reaches IIS at full size, never counts against maxRequestLength, and costs a fraction of the bandwidth — on a phone connection the difference is often the difference between an upload that completes and one that times out. See the full comparison with <asp:FileUpload>.
Shrink images before they are uploaded
A phone photo is often 4-8 MB. Resizing in the browser means that is never transferred, never buffered by IIS, and never counted against maxRequestLength. Set ImageResize="true" and give it a bound:
<au:AjaxFileUpload ID="Uploader1" runat="server" AllowMultiple="true"
ImageResize="true"
ResizeMaxWidth="1600" ResizeMaxHeight="1600"
ResizeQuality="0.82" ResizeFormat="image/webp"
OnFileUploaded="Uploader1_FileUploaded" />
Aspect ratio is preserved - the two maximums are a bounding box, not a target size. ResizeFormat is optional; leave it off to keep the original format. EnableImageResize is a compatibility alias for the same switch.
Reject the wrong images before the upload starts
Dimension rules are evaluated in the browser, so a too-small logo or an enormous scan is refused without a round trip. Turn the check on with EnableImageDimensions and set whichever bounds matter:
| Property | Default | Purpose |
ShowThumbnails | true | Preview each image in the queue before upload. |
EnableImageDimensions | false | Enables the Min/Max width and height checks below. |
MinWidth / MinHeight | 0 | Floor, in pixels. 0 means no floor. |
MaxWidth / MaxHeight | 0 | Ceiling, in pixels. 0 means no ceiling. |
AutoOrient | false | Rotate photos upright from their EXIF orientation tag. EnableExifOrient is an alias. |
Client-side rules are a convenience, not a security boundary - the server re-checks every upload on arrival. See Securing uploads.
Getting the image in
Browse and drag-and-drop are not the only routes. A screenshot is already on the clipboard, so Ctrl+V paste skips saving it to disk first — the uploader names the pasted image from its timestamp and treats it like any other file. Everything on this page applies to a pasted image too.
Cropping
Crop="true" opens the interactive editor before upload; CropAspectRatio locks the box to a ratio - "1" for a square avatar, "16/9" for a banner. Leave it empty for a free crop. EnableImageCrop is an alias for Crop.
Working demos