Read a form

This guide shows you how to read form fields and uploaded files. The same page shows the form and handles the submission.
hello.cow
<?js
import { field } from 'cow:web'
let name = ''
if (req.method() === 'POST') {
  const values = await req.formData()
  name = field(values, 'name')
}
?>
<form method="post">
  <label>Your name <input name="name" maxlength="80"></label>
  <button>Say hello</button>
</form>
<?js if (name) { ?>
  <p>Hello, <?= h(name) ?>!</p>
<?js } ?>
Output — after you submit the name Clover, with blank lines removed
<form method="post">
  <label>Your name <input name="name" maxlength="80"></label>
  <button>Say hello</button>
</form>
  <p>Hello, Clover!</p>
Warning: This example only displays a greeting. Validate fields on the server. For actions that change account or application data, add authorization and CSRF protection.

Read an uploaded file

Use method="post" and enctype="multipart/form-data" on an HTML form with a file input. Read it with await req.formData(). A value is either a string or an upload with name, type, and size.
upload.cow
<?js
let upload = null
if (req.method() === 'POST') {
  const values = await req.formData()
  const file = values.get('attachment')
  if (file && typeof file !== 'string') upload = file
}
?>
<form method="post" enctype="multipart/form-data">
  <label>File <input type="file" name="attachment"></label>
  <button>Upload</button>
</form>
<?js if (upload) { ?>
  <p>Received <?= h(upload.name) ?> (<?= upload.size ?> bytes).</p>
<?js } ?>
Output — after you upload a 12-byte notes.txt, with blank lines removed
<form method="post" enctype="multipart/form-data">
  <label>File <input type="file" name="attachment"></label>
  <button>Upload</button>
</form>
  <p>Received notes.txt (12 bytes).</p>
Uploads belong to the current request and are held in bounded memory. Saving is explicit: call await file.save(absolutePath) with a destination that you choose.
Warning: Do not trust an uploaded filename as a filesystem path. The name and type come from the visitor. Choose the destination yourself, and escape the name with h() when you print it.

Set limits

Cow applies request body and upload limits. By default, the whole request body can be up to 1,048,576 bytes (1 MiB), and req.formData() accepts up to 10 files of up to 1,048,576 bytes each. Cow rejects a form that exceeds the formData() limits in full, with a 413 response and the code COW_FORM_LIMIT.
Check your configured limits before you accept large files. To raise the body limit, start Cow with --body-limit. To change the form limits, pass options such as maxFiles and maxFileSize to req.formData().
Validate content as well as names and types. An interrupted save can leave a partial file, so application code should handle that case.