Skip to content

Instantly share code, notes, and snippets.

@jbruchanov
Created November 10, 2016 14:33
Show Gist options
  • Select an option

  • Save jbruchanov/c6bc463325a6ff5d8725bacf4137f159 to your computer and use it in GitHub Desktop.

Select an option

Save jbruchanov/c6bc463325a6ff5d8725bacf4137f159 to your computer and use it in GitHub Desktop.
AJAX file uploading + progress
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Title</title>
</head>
<script type="application/javascript">
/* //PHP SERVER SIDE
<?php
$code = $_GET['code'];
if(!file_exists ($code)){
mkdir($code, 0777);
}
//var_dump($_FILES);
//die();
$target_dir = "$code" . "/";
$target_file_name = gmdate("YmdHisZ", time());
$target_file = $target_dir . basename($target_file_name);
$uploadOk = 0;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
// var_dump($_POST);
// var_dump($_FILES);
// Check if image file is a actual image or fake image
if(isset($_POST["name"]) && $_POST["name"] == "Submit") {
$check = getimagesize($_FILES["Image"]["tmp_name"]);
move_uploaded_file($_FILES["Image"]["tmp_name"], $target_file);
$uploadOk = 1;
$im = new Imagick($target_file);
$im->scaleImage(0, 200);
$im->writeImage($target_file . "_thumbnail");
}
echo $uploadOk;
?>
*/
//region global helpers
var Ids = {
PreviewImage : "previewImage",
SelectedFile : "selectedFile",
SendFile : "sendFile",
UploadButtonsContainer: "uploadButtonsContainer",
RetryCounter: "retryCounter"
};
if (typeof String.prototype.startsWith != 'function') {
String.prototype.startsWith = function (str) {
return this.slice(0, str.length) == str;
};
}
const CODE = getCode();
const UPLOAD_URL = "http://www.scurab.com/_fujitest/upload.php?code=" + CODE;
const MAX_FILE_SIZE = 20 * 1024 * 1024;//20MiB
function $(name) {
return document.getElementById(name);
}
function newElement(name) {
return document.createElement(name);
}
function newInput(name, type, accept) {
accept = accept || "image/*";
var input = newElement("input");
input.name = name;
input.type = type;
input.accept = accept;
return input;
}
/**
* Create a single form html element for file sending
*
* */
function createFormNode() {
var container = newElement("div");
//form
var form = newElement("form");
container.appendChild(form);
form.method = "POST";
form.action = UPLOAD_URL;
form.enctype = "multipart/form-data";
//input file
var selectFile = newInput("Image", "file");
selectFile.id = Ids.SelectedFile;
selectFile.onchange = function () {
onFileSelected(form, selectFile);
};
form.appendChild(selectFile);
//preview image
var previewImage = newElement("img");
previewImage.id = Ids.PreviewImage;
previewImage.height = "64";
form.appendChild(previewImage);
//input send
var sendFile = newInput("name", "submit", null);
sendFile.id = Ids.SendFile;
sendFile.style.visibility = "hidden";
form.onsubmit = function () {
onFileSend(form, selectFile);
return false;
};
form.appendChild(sendFile);
//assign fields for easier access later
form[Ids.SelectedFile] = selectFile;
form[Ids.PreviewImage] = previewImage;
form[Ids.SendFile] = sendFile;
$(Ids.UploadButtonsContainer).appendChild(container);
}
//endregion
function onInit() {
$("code").innerHTML = CODE;
createFormNode();
}
function onFileSelected(form, src) {
try {
var file = event.target.files[0];
//validation for max file size and existing mime type for image
if (file.size > MAX_FILE_SIZE) {
//clear our already selected stuff
clearSelection(form);
window.alert("Max file size hit!");
return;
} else if (!file.type.startsWith("image/")) {
clearSelection(form);
window.alert("Selected file seems not to be an image!");
return;
}
//update UI to show send button & show preview of selected image
form[Ids.SendFile].style.visibility = "visible";
var reader = new FileReader();
reader.onload = function () {
var previewImage = form[Ids.PreviewImage];
previewImage.setAttribute("src", reader.result);
};
reader.readAsDataURL(file);
} catch (e) {
//not supported?
window.alert(e);
}
}
/**
* Clear all UI controls if something went wrong with selected file
* @param form
*/
function clearSelection(form) {
form[Ids.SelectedFile].value = "";
form[Ids.PreviewImage].setAttribute("src", "");
form[Ids.SendFile].style.visibility = "hidden";
}
/**
*
* @param form form htmlElement
* @param file input htmlElement
*/
function onFileSend(form, file) {
try {
var xhr = new XMLHttpRequest();
var sendButton = form[Ids.SendFile];
//handle progress
xhr.upload.addEventListener('progress', function (ev) {
sendButton.value = Math.round((ev.loaded / ev.total) * 100) + '%';
}, false);
//handle finish
xhr.onreadystatechange = function () {
if (xhr.readyState == 4/*Done*/) {
if (xhr.status == 200) {
sendButton.value = "Finished";
} else {
sendButton.value = "Retry";
sendButton.disabled = false;
form[Ids.RetryCounter] = (form[Ids.RetryCounter] || 0) + 1;
}
}
};
xhr.open('POST', UPLOAD_URL, true);
//build form
var files = file.files;
var data = new FormData();
data.append("name", "Submit");
for (var i = 0; i < files.length; i++) {
data.append("Image", files[i]);
}
xhr.send(data);
//update UI
sendButton.disabled = true;
form[Ids.SelectedFile].disabled = true;
if (form[Ids.RetryCounter] === undefined) {//only if we don't retry
createFormNode();
}
} catch (e) {
window.alert(e);
}
}
//region temp, to remove
function getCode() {
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var dayOfYear = Math.floor((now - start) / (1000 * 86400) /*ONE DAY in ms*/);
var code = toRadix((now.getHours() * 36000) + (now.getMinutes() * 600) + (now.getSeconds() * 10) + (now.getMilliseconds() / 100));
code = toRadix(dayOfYear) + code;
while (code.length < 6) {
code += "X";
}
if(code.length > 6){
code = code.substring(0, 6);
}
return code;
}
function toRadix(number, radix) {
var alphabet = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
radix = radix || alphabet.length;
if (radix > alphabet.length) {
throw "Max radix is:" + alphabet.length;
}
var HexN = "", Q = Math.floor(Math.abs(number)), R;
while (true) {
R = Q % radix;
HexN = alphabet.charAt(R) + HexN;
Q = (Q - R) / radix;
if (Q == 0) break;
}
return ((number < 0) ? "-" + HexN : HexN);
}
//endregion
</script>
<body onload="onInit()">
Code:
<label id="code" style="font-family: monospace"></label><br/>
<div id="uploadButtonsContainer">
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment