Created
November 10, 2016 14:33
-
-
Save jbruchanov/c6bc463325a6ff5d8725bacf4137f159 to your computer and use it in GitHub Desktop.
AJAX file uploading + progress
This file contains hidden or 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 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