Start with the document decision

Before adding an upload control, identify the business decision the file will support. A warranty claim may need a receipt and a photograph of the fault; a quotation request might need a drawing. Those are different documents with different sensitivity and review paths. Ask whether a structured field could replace an attachment, whether a photo is sufficient, and whether the customer can submit the request first and add evidence later. Collecting every possible file in advance increases storage, review work and exposure without necessarily improving a decision. Write down who may upload, which case receives the file, who may view it, and when it should be removed. The customer-facing instruction should name the purpose in ordinary language rather than the internal storage bucket or file-processing system.

Turn that decision into an explicit file contract before building the interface. Specify an allowlist of necessary formats, a maximum size for each file, whether multiple files are allowed, and any image legibility requirement. The size is a product choice based on the actual documents and service capacity; do not borrow an arbitrary number from another site. Explain whether a password-protected document can be reviewed and provide another route when the allowed formats cannot represent a customer’s evidence. Keep the policy consistent between the page, API gateway, application and staff instructions. If one layer accepts a file that another rejects, customers see an unexplained failure after spending time selecting or scanning it.

Explain selection and correction

Place the allowed types and limit next to the labelled file control, before a customer opens the picker. MDN explains that the HTML accept attribute guides which file types the picker offers; it does not validate what the server receives. Use it as a convenience and keep the written rule visible. Make the native control available to keyboard and assistive technology users even if its appearance is customized. After selection, display the filename, size and number of chosen files as text. Provide a clear remove or replace action, especially on mobile where an accidental camera selection is common. A thumbnail can help with photographs, but it cannot prove a scan is readable or that a file is safe.

A useful rejection says which file failed and what the customer can do next. “Receipt.pdf exceeds this form’s stated limit; choose a smaller file or use the alternative contact route” is more actionable than “invalid upload.” Do not erase other completed form fields when the file fails. If a request has several attachments, keep accepted selections visible while marking the rejected one, subject to the browser’s file input security model. The W3C error-identification guidance requires a detected input error to identify the item and describe the problem in text. Test whether the message is reached after submission, can be read when zoomed, and remains associated with the affected control. A generic toast that vanishes can leave the customer unsure whether the request itself was sent.

Validate and isolate the received file

Treat every selected file as untrusted input. OWASP recommends an allowlist of extensions, type checks beyond the client-supplied Content-Type header, size limits, generated storage names and access controls. A filename or browser MIME label is not proof of content. Decode and normalize the name before checking its extension, and reject dangerous naming tricks rather than trying to clean them into executable paths. Where a format supports reliable signature checking, compare the actual bytes with the expected type; that check is one layer, not a guarantee that every file is harmless. Apply malware scanning or content disarm where the workflow and file type justify it. Do not let a failed scan or parser crash silently convert an unreviewed file into an accepted case attachment.

Keep received files outside the executable web application path or on isolated storage with the least permissions needed. An application-generated identifier should bind the stored object to a case; the original filename can remain display metadata after safe handling, but it should not decide the storage path. Authorize both upload and later download against the case, because an opaque URL alone does not prove the reader may see a customer document. Apply size controls at the request boundary and after decompression when archives are allowed. Agree with operations on what happens to pending files, rejected files and abandoned drafts, including deletion and audit information. The practical aim is a traceable attachment that staff can review without exposing it as a public web asset.

Separate selected, received and accepted

Selection on a device, transfer to a server and acceptance into a case are separate events. Show a progress indicator only when there is a real transfer to report; do not imply that a selected file has reached staff. After the server validates the bytes, return a status tied to the individual attachment and its case. If scanning is asynchronous, say that the file is received and pending review, then update the case when the result is known. A completed request should identify which attachments were accepted and provide a reference the customer can use in support. If the network fails, preserve the form where possible and avoid inviting an identical second submission that could create a duplicate case. Recovery language should describe whether to retry the file, the whole request or neither.

Consider a worked warranty example. A customer selects a receipt PDF and two fault photographs. The interface describes the accepted formats and size rule before selection and lists all three names afterward. The receipt passes the server checks, one photo is accepted, and the second photo fails because its actual format differs from the allowed list. The page names that photo, preserves the written claim and the accepted files, and offers a replacement action. The final confirmation names the two accepted files rather than saying merely “success.” Staff see only those case-bound files after authorization. This scenario is a design test, not a claim about a particular shop or its measured failure rate.

Test the handoff, not just the picker

Rehearse a valid file, an unsupported extension, a misleading MIME label, an oversized file, a truncated transfer and an interrupted connection. Check what the customer sees and what the server stores for each. Test a keyboard-only route through selection, removal, error and confirmation; use a screen reader to verify the file label and status language. Check narrow mobile layouts and a zoomed page with a long Chinese filename. Confirm that a customer cannot fetch another case’s document by changing an identifier and that staff roles reveal only the records they need. These are acceptance tests for the actual implementation, not promises that one checklist makes uploads secure.

Keep a short operational script for support. It should let a colleague ask for the case reference, state which attachment is pending or rejected, and explain a safe replacement route without requesting a private document through an unrelated mailbox. Record a reason code for server rejection and a customer-friendly explanation separately; exposing raw scanner output may confuse users or reveal implementation detail. Review real support questions after launch and update the allowed formats or instructions if the same legitimate document repeatedly fails. Do not change the server allowlist merely to suppress an error report. The team should be able to show, for one case, that the visible confirmation matches the bytes retained and the access granted to staff.

For a small team, write the acceptance rule as a decision table that names the file purpose, allowed type, limit, reviewer and fallback channel. Give the support team the same version of that table used by the product team. This prevents a staff member from promising that any file can be sent while the application silently blocks it. Assign an owner to changes: a new file type should be tested for safe handling, readable review and deletion before it is advertised to customers. Review the instructions whenever a case type changes, because an upload that was suitable for a warranty receipt may be inappropriate for identity evidence. This governance work is small, but it keeps the customer promise aligned with the actual system.

Before you proceed

  • Can the customer see purpose, allowed formats and size before choosing a file?
  • Does server validation decide acceptance and keep rejected files out of the case?
  • Can customer and staff distinguish selected, received, pending and accepted attachments?

Sources & further reading