<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Multer on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/multer/</link><description>Recent content in Multer on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 02 Sep 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/multer/index.xml" rel="self" type="application/rss+xml"/><item><title>Uploading files to a web app with Node</title><link>https://blog.iankulin.com/uploading-files-to-a-web-app-with-node/</link><pubDate>Mon, 02 Sep 2024 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/uploading-files-to-a-web-app-with-node/</guid><description>&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-3.09.38-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;My default approach to web apps at the moment is Node/Express SSR. I needed to have users be able to upload files this week, and as usual there&amp;rsquo;s an express middleware that makes it trivial. This post just steps through using &lt;a href="https://github.com/expressjs/multer"&gt;multer&lt;/a&gt; to make it simple to enable file uploads on your website.&lt;/p&gt;
&lt;h3 id="express--middleware"&gt;Express &amp;amp; middleware&lt;/h3&gt;
&lt;p&gt;Before we look at file uploading, it&amp;rsquo;s worth just explaining how it fits with the other tools we&amp;rsquo;re using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en"&gt;Node&lt;/a&gt; - A server runtime that executes javascript. It&amp;rsquo;s a good option for writing web apps if you already know JavaScript from frontend. It has an extensive ecosystem of packages that are installed managed with &lt;a href="https://www.npmjs.com/"&gt;NPM&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt; - A node package that encapsulates a lot of functionality around handling web requests to make it much simpler for the developer. In particular it makes setting up routes easier and introduces the concept of middleware.&lt;/li&gt;
&lt;li&gt;Middleware - in Express we can install middleware - packages that intercept web requests and deal with them or pass them on. Commonly, they work to pull parts of requests out and expose them in developer friendly ways, but they can also do things like apply security rules to requests to allow or deny them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Multer is express middleware to handle data from a web request that includes &amp;ldquo;multipart/form-data&amp;rdquo; - which is what we use for file uploads.&lt;/p&gt;
&lt;h3 id="steps"&gt;Steps&lt;/h3&gt;
&lt;p&gt;Since this is quite a small topic, and I&amp;rsquo;ve started by saying what Node is, I&amp;rsquo;ll pitch these explanations for beginners. I am going to assume you&amp;rsquo;ve been able to install VSCode or some other IDE that you know how to use, that you&amp;rsquo;ve installed Node on the machine you&amp;rsquo;re working on, and you&amp;rsquo;ve got some familiarity with JavaScript &amp;amp; HTML.&lt;/p&gt;
&lt;h4 id="project-setup"&gt;Project Setup&lt;/h4&gt;
&lt;p&gt;Create a directory for your project - I&amp;rsquo;m calling mine &amp;lsquo;file-upload&amp;rsquo; which will be the name of this project. Open VSCode in that directory, and run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install express multer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After a few seconds NPM should have created a couple of files (&lt;code&gt;package.json&lt;/code&gt; &amp;amp; &lt;code&gt;package-lock.json&lt;/code&gt;) and a directory called &lt;code&gt;node_modules&lt;/code&gt;. &lt;code&gt;node_modules&lt;/code&gt; contains all the library code we&amp;rsquo;ll be using, and the package files have some versioning information used by NPM.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.00.01-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.00.01-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is going to be a server that responds to web requests, so we better write a skeleton for that. Create a file called &lt;code&gt;server.js&lt;/code&gt; and add this code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; express &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;express&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; app &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; express&lt;span style="color:#eceff4"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; handle the default route
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;get&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;send&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; Start the server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;listen&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;3000&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; console&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;log&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Listening on http://127.0.0.1:3000&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To start our server, we need to enter this in the terminal:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node server.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.11.02-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Now if you visit the web address &lt;a href="http://127.0.0.1:3000"&gt;http://127.0.0.1:3000&lt;/a&gt; in your web browser, you should see the message &amp;ldquo;hello world&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.15.28-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.15.28-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To stop the server hold down control and press &amp;lsquo;C&amp;rsquo; in the terminal window.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.18.49-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.18.49-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="serving-a-html-file"&gt;Serving a HTML file&lt;/h4&gt;
&lt;p&gt;Sending that &amp;lsquo;hello world&amp;rsquo; text is cool and all, but ideally, our web server would serve a web page. Let&amp;rsquo;s alter the default route of our server to do that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; express &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;express&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; app &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; express&lt;span style="color:#eceff4"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; handle the default route
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;get&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;sendFile&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;__dirname &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;/index.html&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; Start the server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;listen&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;3000&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; console&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;log&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Listening on http://127.0.0.1:3000&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will send the file &lt;code&gt;index.html&lt;/code&gt; instead of just the &amp;lsquo;hello world&amp;rsquo; text from before. The &lt;code&gt;__dirname&lt;/code&gt; part is just saying the index.html file will be in the same directory as our app. We better also create an &lt;code&gt;index.html&lt;/code&gt; there so it can be sent.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;html lang=&amp;#34;en&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;title&amp;gt;Hello&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Hello world
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ah yes. That&amp;rsquo;s much more professional.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.28.36-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-2.28.36-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="multer"&gt;Multer&lt;/h4&gt;
&lt;p&gt;Now it does get a bit more complicated. Multer can use several different types of storage. For example you might want to use an S3 bucket on AWS. We have simpler tastes and just want to store files as files on our host, but the point is the storage engines can be swapped in and out for Multer, so we need to create a Multer storage engine, then a Multer &lt;code&gt;upload&lt;/code&gt; that uses that storage.&lt;/p&gt;
&lt;p&gt;Then the Multer &lt;code&gt;upload&lt;/code&gt; is used in the route for the web request that contains our file. Possibly this explanation is more complicated than the code. Let&amp;rsquo;s have a look:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; express &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;express&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; multer &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;multer&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; fs &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;fs&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; app &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; express&lt;span style="color:#eceff4"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; set up storage engine &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; Multer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; storage &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; multer&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;diskStorage&lt;span style="color:#eceff4"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; destination&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; function &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; file&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; cb&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cb&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;null&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;data/&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; filename&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; function &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; file&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; cb&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cb&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;null&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; file&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;originalname&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; upload &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; multer&lt;span style="color:#eceff4"&gt;({&lt;/span&gt; storage&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; storage &lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; create the &lt;span style="color:#a3be8c"&gt;&amp;#39;data&amp;#39;&lt;/span&gt; directory &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; it doesn&lt;span style="color:#a3be8c"&gt;&amp;#39;t exist &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;!&lt;/span&gt;fs&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;existsSync&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;./data&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;))&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fs&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;mkdirSync&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;./data&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; handle the default route
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;get&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;sendFile&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;__dirname &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;/index.html&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; handle the upload route
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;post&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;/upload&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; upload&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;single&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;file&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;),&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;!&lt;/span&gt;req&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;file&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;return&lt;/span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;status&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;400&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;send&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;No file uploaded.&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;send&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;File uploaded successfully.&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; start the server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;listen&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;3000&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; console&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;log&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Listening on http://127.0.0.1:3000&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ll look at each of these new fragments one at a time:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; multer &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;multer&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; fs &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;fs&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This just pulls in two libraries - &lt;code&gt;multer&lt;/code&gt; for handling the uploads, and &lt;code&gt;fs&lt;/code&gt; which just has some file operations that we&amp;rsquo;ll use for creating the directory for our data.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; set up storage engine &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; Multer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; storage &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; multer&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;diskStorage&lt;span style="color:#eceff4"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; destination&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; function &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; file&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; cb&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cb&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;null&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;data/&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; filename&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; function &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; file&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; cb&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cb&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;null&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; file&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;originalname&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As discussed before, we need to create a storage engine, and these can be of different types. This is the diskStorage type. We&amp;rsquo;ll save the file to the ./data directory and use the original filename it had on the user&amp;rsquo;s machine.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; upload &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; multer&lt;span style="color:#eceff4"&gt;({&lt;/span&gt; storage&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; storage &lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This creates the upload handler with that storage engine we created in the previous step.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;// create the &amp;#39;data&amp;#39; directory if it doesn&amp;#39;t exist 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;if (!fs.existsSync(&amp;#34;./data&amp;#34;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fs.mkdirSync(&amp;#34;./data&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;d get an error if multer tries to write to the directory we told it to when we created the storage engine and the directory did not exist. So we check for that here and create it if needed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; handle the upload route
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;post&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;/upload&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; upload&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;single&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;file&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;),&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;!&lt;/span&gt;req&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;file&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;return&lt;/span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;status&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;400&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;send&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;No file uploaded.&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;send&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;File uploaded successfully.&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s our route handler. Any POST requests to hrrp://127.0.0.1:3000/upload will be sent here. It passes off the file contained in the request to our Multer upload, and if that all works, it sends a message back to the browser.&lt;/p&gt;
&lt;h4 id="html-form"&gt;HTML form&lt;/h4&gt;
&lt;p&gt;We need a way for the /upload route to be hit with the file data, and that&amp;rsquo;s done by submitting a form with the file data. Let&amp;rsquo;s edit out index.html to do that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;&amp;lt;!&lt;/span&gt;DOCTYPE html&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;html lang&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;head&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;meta charset&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;title&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#bf616a"&gt;File&lt;/span&gt; Upload&lt;span style="color:#81a1c1"&gt;&amp;lt;/&lt;/span&gt;title&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;/&lt;/span&gt;head&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;body&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;form action&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;/upload&amp;#34;&lt;/span&gt; method&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;post&amp;#34;&lt;/span&gt; enctype&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;multipart/form-data&amp;#34;&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;input type&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;file&amp;#34;&lt;/span&gt; name&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;file&amp;#34;&lt;/span&gt; id&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;file&amp;#34;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;input type&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;submit&amp;#34;&lt;/span&gt; value&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Upload&amp;#34;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;/&lt;/span&gt;form&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;/&lt;/span&gt;body&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;&amp;lt;/&lt;/span&gt;html&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That &lt;code&gt;enctype&lt;/code&gt; of &lt;code&gt;&amp;quot;multipart/form-data&amp;quot;&lt;/code&gt; is important. That&amp;rsquo;s what Multer wants to see. Apart from that, this is just a form with two buttons. The first one lets the user choose a file, and the second &amp;ldquo;Upload&amp;rdquo; button submits it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-3.00.01-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-3.00.01-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Clicking on the &amp;ldquo;Browse&amp;hellip;&amp;rdquo; button will open the file selection dialog for your operating system. Once you&amp;rsquo;ve selected a file, the name will be shown.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-3.03.39-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-3.03.39-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we press the Upload button, that file will now be sent to the server, and should appear in the &lt;code&gt;data&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-3.07.20-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-08-18-at-3.07.20-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;This is about the simplest I think we can make this. As always there are a heap of other considerations when implementing this in a live app. For example, I feel uncomfortable using the user submitted file name - perhaps they could manipulate this to be something like &lt;code&gt;./../server.js&lt;/code&gt; and overwrite our source code. We should probably sanitize that, or just replace it with a name we generate. We also should be thinking about restricting the size and or type of files the user can upload, and gracefully handle the errors if we run out of space or some other disaster befalls our system.&lt;/p&gt;</description></item></channel></rss>