Search code examples
javascriptformsuploaddenooak

Handling multipart/form-data with Deno and Oak


I'm making slow but steady progress in learning Deno and Oak but this has me stumped. I have a simple web form with a file upload field:

<form method="post" action="/quote" enctype="multipart/form-data">
  <label>Author:
  <input type="text" name="author" />
  </label>
  <label>file: <input type="file" name="myfile" multiple />
  </label>
  <label>Quote: 
  <textarea name="quote"></textarea>
  </label>
  <input type="submit" />
  </form>

The processing is done with Deno and Oak and here is the script that handles the text data:

router.post('/quote', async context => {
const body = context.request.body({ type: 'form' })
  const value = await body.value
  const author = value.get('author')
  console.log(author)
  context.response.redirect(`/?author=${author}`)
})

The route can handle a form which does not have an encoding of multipart/form-data but as soon as I add that, the author field is undefined.

My question is: how can I access the data from this form (both the text and file data)?


Solution

  • Here's an update for Oak 16+, and how to save the file on the server. The syntax seems to have changed quite a bit for some things.

    I have routing set up with

    import { Router } from "jsr:@oak/oak@16";
    const router = new Router();
    
    import handlers from "./requestHandlers.ts";
    
    router
      .post("/upload", handlers.handleUpload);
    

    And then in my request handlers (I have UPLOAD_PATH defined as a constant elsewhere):

    handleUpload: async  ({ request, response }: { request: any; response: any }) => {
        const theBody: Body = await request.body;
        const form: FormData = await theBody.formData()
        const theFile: File = form.get("file") as File;
        const destPath = `${config.UPLOAD_PATH}${theFile.name}`;
        const fileData = await theFile.stream()
        Deno.writeFile(destPath, fileData);
    
        response.body = `Uploaded file size: ${theFile.size}`;
      }