Last active
July 21, 2023 05:39
-
-
Save duhaime/e5b3fd78c014423f37428dc23caced12 to your computer and use it in GitHub Desktop.
Minimal Multiple File Uploads with Vue + Node or Flask 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
*.pem | |
*.swp | |
*.DS_Store | |
__pycache__/ | |
node_modules/ | |
uploaded_files/ |
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> | |
<head> | |
<meta charset='UTF-8'> | |
<title>title</title> | |
<script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script> | |
<style> | |
.button { | |
background: #009fff; | |
color: #fff; | |
padding: 10px 20px; | |
display: inline-block; | |
border-radius: 3px; | |
box-shadow: 0px 0px 5px #aaa; | |
font-family: arial; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='app'> | |
{{ message }} | |
<form id='upload-form'> | |
<input | |
name='title' | |
type='text' | |
placeholder='title'> | |
<input | |
id='file-field' | |
name='files' | |
type='file' | |
multiple> | |
<div> | |
<div class='button' v-on:click='uploadForm'>Submit</div> | |
</div> | |
</form> | |
</div> | |
<script> | |
var app = new Vue({ | |
el: '#app', | |
data: { | |
message: '' | |
}, | |
methods: { | |
uploadForm: function(e) { | |
// update the message state | |
this.message = 'All done!'; | |
// send the form with vanilla js | |
var formElement = document.querySelector('#upload-form'), | |
fileElement = document.querySelector('#file-field'), | |
request = new XMLHttpRequest(), | |
data = new FormData(formElement); | |
//data.append('files', fileElement.files); | |
request.open('POST', 'http://localhost:5000/uploads', true); | |
request.send(data); | |
// stop the event from propagating so route won't change | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
} | |
}) | |
</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
{ | |
"name": "c393eefe3e25f925ab5a42e093dfc9a0", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"repository": { | |
"type": "git", | |
"url": "git+https://gist.github.com/c393eefe3e25f925ab5a42e093dfc9a0.git" | |
}, | |
"author": "", | |
"license": "ISC", | |
"bugs": { | |
"url": "https://gist.github.com/c393eefe3e25f925ab5a42e093dfc9a0" | |
}, | |
"homepage": "https://gist.github.com/c393eefe3e25f925ab5a42e093dfc9a0", | |
"dependencies": { | |
"body-parser": "^1.18.3", | |
"express": "^4.16.4", | |
"multer": "^1.4.1" | |
} | |
} |
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
// usage: node server.js | |
const express = require('express') | |
const multer = require('multer') | |
const app = express() | |
const path = require('path') | |
const fs = require('fs') | |
const port = 5000 | |
// configure file uploads | |
app.use(require('body-parser').json()); | |
const storage = multer.diskStorage({ | |
destination(req, file, cb) { | |
cb(null, 'uploaded_files'); | |
}, | |
filename(req, file, cb) { | |
cb(null, file.originalname); | |
} | |
}); | |
// make the folder where uploads will be kept | |
if (!fs.existsSync('uploaded_files')) fs.mkdirSync('uploaded_files'); | |
app.post('/uploads', multer({ storage: storage }).any(), function(req, res, next) { | |
console.log('uploading', req.files, req.body) | |
}) | |
// serve the html content on the default route | |
app.get('/', function(req, res) { | |
res.sendFile(path.join(__dirname, 'index.html')) | |
}) | |
// serve the application | |
app.listen(port, function() { | |
console.log(`Example app listening on port ${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
# usage: export FLASK_APP=server.py && flask run | |
from flask import Flask, flash, request, redirect, url_for, send_from_directory | |
from werkzeug.utils import secure_filename | |
import os | |
UPLOAD_FOLDER = 'uploaded_files' | |
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif']) | |
if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER) | |
app = Flask(__name__) | |
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER | |
@app.route('/uploads', methods=['POST']) | |
def upload_file(): | |
print(' * received form with', list(request.form.items())) | |
# check if the post request has the file part | |
for file in request.files.getlist('files'): | |
if file and file.filename.split('.')[-1].lower() in ALLOWED_EXTENSIONS: | |
filename = secure_filename(file.filename) | |
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) | |
print(' * file uploaded', filename) | |
return redirect('/') | |
@app.route('/') | |
def hello_world(): | |
return send_from_directory('.', 'index.html') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment