Created
October 2, 2022 14:22
-
-
Save daveknights/514e1460677a325b3ae96edece03d6c5 to your computer and use it in GitHub Desktop.
Upload images to Node server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require('http') | |
const fs = require('fs') | |
const path = require('path') | |
const formidable = require('formidable') | |
const static = require('node-static') | |
const fileServer = new(static.Server)('./public') | |
const hostname = '127.0.0.1' | |
const port = 4000 | |
const imgExtensions = ['.jpg', '.png', '.webp'] | |
const server = http.createServer((req, res) => { | |
res.setHeader('Access-Control-Allow-Origin', '*') | |
res.setHeader('Access-Control-Allow-Methods', 'POST') | |
if (req.url === '/upload' && req.method.toLowerCase() === 'post') { | |
const form = formidable({ multiples: true }) | |
form.parse(req, (err, fields, files) => { | |
let uploaded = false | |
let error = false | |
if (err) { | |
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' }) | |
res.end(String(err)) | |
return | |
} | |
const oldPath = files.file.filepath | |
const newPath = `${path.join(__dirname, 'public')}/${files.file.originalFilename}` | |
const rawData = fs.readFileSync(oldPath) | |
fs.writeFile(newPath, rawData, err => { | |
err ? error = err : uploaded = true | |
res.writeHead(200, { 'Content-Type': 'application/json' }) | |
res.end(JSON.stringify({ uploaded: uploaded, error: error }, null, 2)) | |
}) | |
}) | |
} | |
if (req.url === '/images') { | |
const validImages = [] | |
fs.readdir(`${__dirname}/public`, (err, files) => { | |
if (err) | |
console.log(err) | |
else { | |
for (const file of files) { | |
if (imgExtensions.includes(path.extname(file))) | |
validImages.push(file) | |
} | |
res.writeHead(200, { 'Content-Type': 'application/json' }) | |
res.end(JSON.stringify({ validImages }, null, 2)) | |
} | |
}) | |
} | |
if (imgExtensions.some(ext => req.url.includes(ext))) | |
fileServer.serve(req, res) | |
return | |
}) | |
server.listen(port, hostname, () => console.log(`Server running at http://${hostname}:${port}/`)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let dropZone; | |
let imageGallery; | |
let galleryHeader; | |
const server = 'http://localhost:4000/'; | |
const showImages = async () => { | |
const response = await fetch(`${server}images`); | |
const jsonResponse = await response.json(); | |
imageGallery.innerHTML = ''; | |
jsonResponse.validImages.length && galleryHeader.classList.add('show'); | |
for (const image of jsonResponse.validImages) { | |
const img = document.createElement('img'); | |
img.src = `${server}${image}`; | |
imageGallery.appendChild(img); | |
} | |
}; | |
const uploadFile = async file => { | |
const formData = new FormData(); | |
formData.append('file', file); | |
const response = await fetch(`${server}upload`, { | |
method: 'POST', | |
body: formData | |
}); | |
const jsonResponse = await response.json(); | |
jsonResponse.uploaded && showImages(); | |
jsonResponse.error && console.log(jsonResponse.error); | |
}; | |
const init = () => { | |
dropZone = document.querySelector('#drop-zone'); | |
galleryHeader = document.querySelector('h3'); | |
imageGallery = document.querySelector('#image-gallery'); | |
for (const eventType of ['dragenter', 'dragover', 'dragleave', 'drop']) { | |
dropZone.addEventListener(eventType, e => e.preventDefault()); | |
} | |
dropZone.addEventListener('dragover', () => dropZone.classList = 'drag-over'); | |
dropZone.addEventListener('drop', e => { | |
if (e.dataTransfer.items) { | |
for (const item of [...e.dataTransfer.items]) { | |
if (item.kind === 'file') { | |
const file = item.getAsFile(); | |
uploadFile(file); | |
} | |
} | |
} else { | |
for (const file of [...e.dataTransfer.files]) { | |
uploadFile(file); | |
} | |
} | |
dropZone.classList = ''; | |
}); | |
showImages(); | |
}; | |
window.addEventListener('load', init); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Upload to node server</title> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<body> | |
<main class="container"> | |
<h1>Drag & Drop Image Uploader</h1> | |
<div id="drop-zone"> | |
<h2>Drag file here to upload</h2> | |
</div> | |
<h3>Uploaded imgages</h3> | |
<div id="image-gallery"></div> | |
</main> | |
<script src="image-upload.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
border: 0; | |
box-sizing: border-box; | |
font-family: Arial, Helvetica, sans-serif; | |
margin: 0; | |
} | |
:root { | |
--primary-colour: 30, 144, 255; | |
--highlight-colour: 7,129,140; | |
} | |
h3 { | |
display: none; | |
margin: 20px 0; | |
} | |
.show { | |
display: block; | |
} | |
.container { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
margin: 30px auto 0; | |
padding: 0 30px; | |
max-width: 800px; | |
} | |
#drop-zone { | |
background: rgba(var(--primary-colour), 0.1); | |
border: dashed 3px rgb(var(--primary-colour)); | |
color: rgb(var(--primary-colour)); | |
height: 300px; | |
margin-top: 30px; | |
padding: 30px; | |
text-align: center; | |
width: 100%; | |
} | |
#drop-zone.drag-over { | |
background: rgba(var(--highlight-colour), 0.1); | |
border-color: rgb(var(--highlight-colour)); | |
color: rgb(var(--highlight-colour)); | |
} | |
#image-gallery { | |
display: grid; | |
gap: 20px; | |
grid-template-columns: repeat(4, 1fr); | |
width: 100%; | |
} | |
#image-gallery img { | |
height: auto; | |
width: 100%; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment