2021-04-08 09:14:59 +03:00
..
2021-03-31 12:34:03 +03:00
2021-03-25 01:59:19 +03:00
2021-04-08 09:14:59 +03:00
2021-04-08 09:14:59 +03:00

g-upload


This example shows an upload form at http://localhost:8080, which allows sending multiple files. When they are sent, the example responds with a page listing their file sizes:

let home request =
  <html>
    <body>
      <%s! Dream.form_tag ~action:"/" ~enctype:`Multipart_form_data request %>
        <input name="files" type="file" multiple>
        <button>Submit!</button>
      </form>
    </body>
  </html>

let report files =
  <html>
    <body>
%     files |> List.iter begin fun (name, content) ->
        <p><%s name %>: <%i String.length content %> bytes</p>
%     end;
    </body>
  </html>

let () =
  Dream.run
  @@ Dream.logger
  @@ Dream.memory_sessions
  @@ Dream.router [

    Dream.get  "/" (fun request ->
      Dream.respond (home request));

    Dream.post "/" (fun request ->
      match%lwt Dream.multipart request with
      | `Ok ["files", `Files files] -> Dream.respond (report files)
      | _ -> Dream.empty `Bad_Request);

  ]
  @@ Dream.not_found
$ dune exec --root . ./upload.exe

The page shown after uploading looks like this:

foo.png, 663959 bytes
bar.png, 1807 bytes

This example uses Dream.multipart (named after Content-Type: multipart/form-data). Dream.multipart receives entire files into strings. Size limits will be added in one of the early alphas. However, this is only good for rare, small uploads, such as user avatars, or for prototyping.

For more heavy usage, see Dream.upload for streaming file uploads.


Security

Dream.multipart behaves just like Dream.form when it comes to CSRF protection. See example d-form. We still use Dream.form_tag to generate the form in the template. The only difference is that we now pass it ~enctype:`Multipart_form_data to make its output look like this:

<form method="POST" action="/" enctype="multipart/form-data">
  <input name="dream.csrf" type="hidden" value="...">

  <!-- Our fields -->
  <input name="files" type="file" multiple>
  <button>Submit!</button>
</form>

By contrast with Dream.multipart, Dream.upload offers no built-in CSRF protection at all at present. You can, however, still use Dream.form_tag, and manually call Dream.verify_csrf_token when you stream a dream.csrf field. You'll then have to decide what to do about files already received.



Next steps:

  • h-sql runs SQL queries against a database.
  • i-graphql handles GraphQL queries and serves GraphiQL.

Up to the tutorial index