DEV Community

Cover image for Uploading files with Deno
Scott Lepper
Scott Lepper

Posted on

Uploading files with Deno

Here I will show a quick tutorial of how to upload files using Deno. Files will simply be stored to disk along with the ability to view them in a browser.

First of all, install Deno.

Now we will add a file to serve our app. Create a project folder to contain your app, then add a subfolder called server. We will also create a client to test it, having a server and client folder will help organize our project.

Add a server.ts file to your server folder. And add the code:

import { Application, send } from "https://deno.land/x/oak/mod.ts";
import { FormFile, multiParser } from 'https://deno.land/x/multiparser@v2.1.0/mod.ts'
import { oakCors } from "https://deno.land/x/cors/mod.ts";

const app = new Application();

app.use(
  oakCors({
    origin: true
  }),
);

app.use(async (ctx) => {
  const path = ctx.request.url.pathname;
  if (path === '/upload') {
    const form = await multiParser(ctx.request.serverRequest)
    if (form) {
      const image: FormFile = form.files.image as FormFile
      try {
        await Deno.writeFile(`images/${image.filename}`, image.content);
      } catch (e) {
        console.error(e)
      }
    }
    ctx.response.body = '{"status": "ok"}';
  }

  if (ctx.request.method === 'GET' && path.startsWith('/images')) {
    await send(ctx, ctx.request.url.pathname, {
      root: `${Deno.cwd()}`
   });
  }
});

app.listen({ port: 8082 });
Enter fullscreen mode Exit fullscreen mode

What is happening here?

  • At the top we import our dependencies
  • Then we create an app, then app.use to register middleware.
  • oakCors will allow any client to call the server (ok for a demo)
  • In the second app.use block we define routes: /upload and /images. From the client we will post to /upload and we can use /images to view the images.
  • /upload gets a file from a posted form and writes it to a folder

Now let's run the app. We need to set permissions to allow-net for http calls, and allow-write/allow-read for writing and reading the images. Then we tell deno to run our server.ts file.

deno run \
--allow-net \
--allow-write=./images \
--allow-read=./,./images \
./server/server.ts
Enter fullscreen mode Exit fullscreen mode

Now let's add the client. Add a client folder and create an index.html file with the following:

<html>
  <head>
    <script src="./index.js"></script>
  </head>
  <body>
    <input type="file" name="file" id="imgfile" onchange="loadImage()">
    <input type='button' id='btnLoad' value='Upload' onclick="upload()" />
    <canvas id="canvas"></canvas>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Now add an index.js file with:

async function post(canvas, name) {
  const ts = new Date().getTime();
  canvas.toBlob(async function(blob) {
    const formData = new FormData();
    formData.append('image', blob, name);
    const res = await fetch('http://localhost:8082/upload', {
      mode: 'no-cors',
      method: 'POST',
      body: formData
    });
  });
}

function loadImage() {
  let img;

  const input = document.getElementById('imgfile');
  if (!input.files[0]) {
      write("Please select a file before clicking 'Load'");
      return;
  }

  const file = input.files[0];
  const fr = new FileReader();
  fr.onload = createImage;
  fr.readAsDataURL(file);

  function createImage() {
      img = new Image();
      img.onload = imageLoaded;
      img.src = fr.result;
  }

  function imageLoaded() {
      const canvas = document.getElementById("canvas")
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext("2d");
      ctx.drawImage(img,0,0);
  }

}

async function upload() {
  const canvas = document.getElementById("canvas")
  const input = document.getElementById('imgfile');
  await post(canvas, input.files[0].name);
  write('File uploaded')
}

function write(msg) {
  const p = document.createElement('p');
  p.innerHTML = msg;
  document.body.appendChild(p);
}
Enter fullscreen mode Exit fullscreen mode

Now open the index.html file, select your image, and upload it! We could serve this page with Deno, but we don't really need to for this demo.

To view your uploaded image, you can go to: localhost:8082/images/[yourimagename]

Here is the full GitHub Project

As you can see, Deno is super easy, fun and fast! Happy coding!

Top comments (1)