Skip to content

Instantly share code, notes, and snippets.

@ObjSal
Last active April 24, 2023 23:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ObjSal/7213828e13b277143dcd28212986a4be to your computer and use it in GitHub Desktop.
Save ObjSal/7213828e13b277143dcd28212986a4be to your computer and use it in GitHub Desktop.
Upload an image from a website to a node.js server, then the node server is going to upload and then download the image from a FTP server and send it back as response to the website.
// Author: Salvador Guerrero
const http = require('http');
const fs = require('fs')
// Third-party modules
const ftp = require("basic-ftp")
var {Base64Encode} = require('base64-stream')
let port = 3000
http.createServer((req, response) => {
/**
* `/` loads index.html
*/
if (req.url == '/' && req.method.toLowerCase() == 'get') {
response.setHeader('Content-Type', 'text/html')
const stream = fs.createReadStream(`${__dirname}/zindex.html`)
// No need to call res.end() because pipe calls it automatically
stream.pipe(response)
}
/**
* `/fileUpload` only works with POST
* Saves uploaded files to the root
*/
else if (req.url == '/fileUpload' && req.method.toLowerCase() == 'post') {
let contentLength = parseInt(req.headers['content-length'])
if (isNaN(contentLength) || contentLength <= 0 ) {
response.statusCode = 411;
response.end(JSON.stringify({status: 'error', description: 'No File'}))
return
}
// Try to use the original filename
let filename = req.headers['filename']
if (filename == null) {
filename = "file." + req.headers['content-type'].split('/')[1]
}
const client = new ftp.Client(/*timeout = 180000*/) // 2min timeout for debug
client.ftp.verbose = true
client.access({
host: "localhost",
user: "anonymous",
password: "",
secure: false
}).then(ftpResponse => {
(async () => {
try {
// Upload the image to the FTP server
await client.uploadFrom(req, `uploads/${filename}`)
// Download the image from the FTP server and send it as response
response.setHeader('Content-Type', req.headers['content-type'])
var base64Encoder = new Base64Encode()
base64Encoder.pipe(response)
await client.downloadTo(base64Encoder, `uploads/${filename}`)
}
catch(err) {
console.log(err)
response.statusCode = 400;
response.setHeader('Content-Type', 'application/json')
response.end(JSON.stringify({status: 'error', description: error}))
}
client.close()
})();
})
}
/**
* Error on any other path
*/
else {
response.setHeader('Content-Type', 'text/html')
response.end('<html><body><h1>Page Doesn\'t exist<h1></body></html>')
}
}).listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
})
<html>
<head>
<script>
const handleImageUpload = event => {
const file = event.target.files[0]
if (file == null) return
fetch('/fileUpload', {
headers: {
'filename': file.name
},
method: 'POST',
body: file
})
.then(response => {
let contentType = response.headers.get('Content-Type')
response.text().then(text => {
document.getElementById("img").src = `data:${contentType};base64,${text}`
})
.catch(error => {
console.error(error)
})
})
.catch(error => {
console.error(error)
})
}
function init() {
document.getElementById('fileUpload').addEventListener('change', event => {
handleImageUpload(event)
})
}
</script>
</head>
<body onload="init()">
<input id="fileUpload" type="file" accept="image/*" /><br />
<img id="img" alt="Uploaded image"/>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment