{"id":284,"date":"2020-06-08T13:09:54","date_gmt":"2020-06-08T04:09:54","guid":{"rendered":"https:\/\/blog.wsd.sh\/?p=284"},"modified":"2020-06-08T13:13:35","modified_gmt":"2020-06-08T04:13:35","slug":"nodejs-book-chapter-7","status":"publish","type":"post","link":"https:\/\/blog.wsd.sh\/?p=284","title":{"rendered":"Nodejs Book: Chapter 7"},"content":{"rendered":"<p>In the previous chapter we added onto our basic ajax example and added the option<br \/>\nto upload a JSON formatted string and parse it on the server. So how do we handle<br \/>\nother functionality, like uploading a file? In this example we will make another<br \/>\nsimple example, where we make a form to upload a jpg image and save it on the server.<br \/>\nOnce the image is saved on the server we will display it on the client.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-285\" src=\"https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_09-300x233.jpg\" alt=\"\" width=\"300\" height=\"233\" srcset=\"https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_09-300x233.jpg 300w, https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_09-1024x796.jpg 1024w, https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_09-768x597.jpg 768w, https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_09.jpg 1140w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<pre>- api.js\n+ public\/\n| - upload.html\n| - + js\/\n| --- upload.js\n| - + img\/\n<\/pre>\n<p>Our directory layout for this example should look like above. We&#8217;ll start with<br \/>\nthe client code as it hasn&#8217;t changed too much from the last chapter.<\/p>\n<p>File: upload.html<\/p>\n<pre>&lt;!DOCTYPE HTML&gt;\n&lt;html&gt;\n\n    &lt;head&gt;\n\n        &lt;meta charset=\"utf-8\"\/&gt;\n        &lt;title&gt;Ajax Request&lt;\/title&gt;\n\n    &lt;\/head&gt;\n\n    &lt;body&gt;\n\n        &lt;input type=\"file\" id=\"fileUpload\"\/&gt;\n        &lt;button id=\"clickBtn\"&gt;Click Me!&lt;\/button&gt;&lt;br&gt;\n        &lt;img id=\"responseImage\"&gt;&lt;\/img&gt;\n\n        &lt;script type=\"text\/javascript\" src=\"js\/upload.js\"&gt;&lt;\/script&gt;\n\n    &lt;\/body&gt;\n\n&lt;\/html&gt;\n<\/pre>\n<p>For the html side we have a file select input and an image with no src, which<br \/>\nwe will replace once our image has uploaded.<\/p>\n<p>File: js\/upload.js<\/p>\n<pre>\"use strict\";\n\nvar fileUpload = document.getElementById(\"fileUpload\");\nvar clickBtn = document.getElementById(\"clickBtn\");\nvar responseImage = document.getElementById(\"responseImage\");\n\nclickBtn.addEventListener(\"click\", function (event) {\n\n    if(!fileUpload.files.length){\n        alert(\"Please select a file!\");\n        return;\n    }\n\n    var file = fileUpload.files[0];\n    var reader = new FileReader();\n    reader.readAsArrayBuffer(file);\n\n    reader.addEventListener(\"load\", function(event){\n\n        var xml = new XMLHttpRequest();\n        xml.open(\"POST\", \"\/api\/upload\", true);\n        xml.send(event.target.result);\n\n        xml.onload = function() {\n\n            var image = document.createElement(\"img\");\n            image.setAttribute(\"src\", xml.responseText);\n\n            image.onload = function() {\n\n                responseImage.parentNode.replaceChild(image, responseImage);\n                responseImage = image;\n\n            }\n\n        }\n\n    });\n\n});\n<\/pre>\n<p>Our client side Javascript file has a few more lines added to it. First we check<br \/>\nto see if a file has been selected. If not file has been selected, then we don&#8217;t<br \/>\nattempt to upload anything.<\/p>\n<p>If a file is selected, then we read it as an ArrayBuffer, and initiate and Ajax<br \/>\nrequest. When we send the request, we send the ArrayBuffer we read from the file<br \/>\ninput. The concept of an array buffer is a little hard to grasp at first, but ultimately<br \/>\nit&#8217;s not very difficult. When information is stored on your computer, it&#8217;s stored<br \/>\nusing a binary sequence of 1&#8217;s and 0&#8217;s. In the case of images this generally means<br \/>\nstoring the red, green and blue values for each pixel in the image.<\/p>\n<p>When we read and ArrayBuffer, we are simply reading the raw information from the<br \/>\nhard drive and keeping it in memory in our client Javascript. When we run<br \/>\n&#8220;`xml.send()&#8220;` with the ArrayBuffer paramter included, we are sending the exact<br \/>\ninformation stored on the harddrive on the client computer to the server.<\/p>\n<p>File: callback.js<\/p>\n<pre>\"use strict\";\n\nconst fs = require(\"fs\");\nconst http = require(\"http\");\nconst uniqid= require(\"uniqid\");\nconst handleFile = require(\"handle-file\");\n\nconst server = http.createServer();\nserver.on(\"request\", handleRequest);\nserver.listen(8080, handleListen);\n\nfunction handleRequest(req, res) {\n\n        console.log(req.method);\n\n        if(req.method === \"GET\") {\n\n                handleFile(req, res);\n\n        } else if(req.method === \"POST\") {\n\n                switch(req.url) {\n                        case \"\/api\/hello\":\n\n                                api_say_hello(req, res);\n\n                        break;\n                        case \"\/api\/upload\":\n\n                                api_upload_file( req, res );\n\n                        break;\n                        default:\n\n                                res.writeHead( 204, { \"Content-Type\" : \"text\/plain\" });\n                                res.end( \"Empty Response\" );\n\n                        break;\n                }\n\n        } else {\n\n                res.writeHead( 204, { \"Content-Type\" : \"text\/plain\" });\n                res.end( \"Empty Response\" );\n\n        }\n\n}\n\nfunction handleListen( ) {\n\n        console.log(\"Server is listening on port 8080\");\n\n}\n\nfunction api_upload_file( req, res ) {\n\n        let str = \"\/img\/\" + uniqid() + \".jpg\";\n        let writeStream = fs.createWriteStream(\".\/public\" + str);\n        req.pipe(writeStream);\n\n        req.on(\"end\", function() {\n\n                res.writeHead(200, { \"Content-Type\" : \"text\/plain\" });\n                res.end(str);\n\n        });\n\n}\n<\/pre>\n<p>There&#8217;s not too many changes. In this case, when we send an ArrayBuffer from the<br \/>\nclient to the server, we skip sending the filename. So in this case we use the<br \/>\nuniqid library to create a random name for us. The uniqid library can be<br \/>\ninstalled with<\/p>\n<pre> $ npm install uniqid\n<\/pre>\n<p>Also since we don&#8217;t have the file name, we assume a JPG type file. It&#8217;s a little<br \/>\nprimitive, but we&#8217;re still working on a proof of concept. So this amount of functionality<br \/>\nis okay for now. As for the file actually being saved to the server, similar to<br \/>\nserving files, writing them is largely the same. We pipe the input from the<br \/>\nrequest directly to the hard drive. Once we&#8217;re done we tell the client where<br \/>\nthe image can be loaded from to display on the client.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now that we&#8217;ve started to make calls to the server, in this chapter we go over how to upload an image. This consists of taking a file from the client and uploaded it as an http request, and reading the request body on the server and writing the data to a file. <\/p>\n","protected":false},"author":1,"featured_media":249,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false},"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/284"}],"collection":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=284"}],"version-history":[{"count":3,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/284\/revisions"}],"predecessor-version":[{"id":289,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/284\/revisions\/289"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/media\/249"}],"wp:attachment":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=284"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=284"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=284"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}