Skip to content

Instantly share code, notes, and snippets.

@iegik
Created July 28, 2013 10:29
Show Gist options
  • Select an option

  • Save iegik/6098162 to your computer and use it in GitHub Desktop.

Select an option

Save iegik/6098162 to your computer and use it in GitHub Desktop.
Both: drag-n-drop and old-style upload form.
"use strict";
/*\
|*|
|*| :: XMLHttpRequest.prototype.sendAsBinary() Polifyll ::
|*|
|*| https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#sendAsBinary()
\*/
if (!XMLHttpRequest.prototype.sendAsBinary) {
XMLHttpRequest.prototype.sendAsBinary = function (sData) {
var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);
for (var nIdx = 0; nIdx < nBytes; nIdx++) {
ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;
}
/* send as ArrayBufferView...: */
this.send(ui8Data);
/* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */
};
}
/*\
|*|
|*| :: AJAX Form Submit Framework ::
|*|
|*| https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntax:
|*|
|*| AJAXSubmit(HTMLFormElement);
\*/
var AJAXSubmit = (function () {
function ajaxSuccess (evn) {
console.log(evn.target.responseText);
//alert(this.responseText);
/* you can get the serialized data through the "submittedData" custom property: */
/* alert(JSON.stringify(this.submittedData)); */
}
function submitData (oData) {
/* the AJAX request... */
var oAjaxReq = new XMLHttpRequest();
oAjaxReq.submittedData = oData;
oAjaxReq.onload = ajaxSuccess;
if (oData.technique === 0) {
/* method is GET */
oAjaxReq.open("get", oData.receiver.replace(/(?:\?.*)?$/, oData.segments.length > 0 ? "?" + oData.segments.join("&") : ""), true);
oAjaxReq.send(null);
} else {
/* method is POST */
oAjaxReq.open("post", oData.receiver, true);
if (oData.technique === 3) {
/* enctype is multipart/form-data */
var sBoundary = "---------------------------" + Date.now().toString(16);
oAjaxReq.setRequestHeader("Content-Type", "multipart\/form-data; boundary=" + sBoundary);
oAjaxReq.sendAsBinary("--" + sBoundary + "\r\n" + oData.segments.join("--" + sBoundary + "\r\n") + "--" + sBoundary + "--\r\n");
} else {
/* enctype is application/x-www-form-urlencoded or text/plain */
oAjaxReq.setRequestHeader("Content-Type", oData.contentType);
oAjaxReq.send(oData.segments.join(oData.technique === 2 ? "\r\n" : "&"));
}
}
return oAjaxReq;
}
function processStatus (oData) {
if (oData.status > 0) { return false; }
/* the form is now totally serialized! do something before sending it to the server... */
/* doSomething(oData); */
/* console.log("AJAXSubmit - The form is now serialized. Submitting..."); */
return submitData (oData);
}
function pushSegment (oFREvt) {
this.owner.segments[this.segmentIdx] += oFREvt.target.result + "\r\n";
this.owner.status--;
processStatus(this.owner);
}
function plainEscape (sText) {
/* how should I treat a text/plain form encoding? what characters are not allowed? this is what I suppose...: */
/* "4\3\7 - Einstein said E=mc2" ----> "4\\3\\7\ -\ Einstein\ said\ E\=mc2" */
return sText.replace(/[\s\=\\]/g, "\\$&");
}
function SubmitRequest (oTarget) {
var nFile, sFieldType, oField, oSegmReq, oFile, bIsPost = oTarget.method.toLowerCase() === "post";
/* console.log("AJAXSubmit - Serializing form..."); */
this.contentType = bIsPost && oTarget.enctype ? oTarget.enctype : "application\/x-www-form-urlencoded";
this.technique = bIsPost ? this.contentType === "multipart\/form-data" ? 3 : this.contentType === "text\/plain" ? 2 : 1 : 0;
this.receiver = oTarget.action;
this.status = 0;
this.segments = [];
var fFilter = this.technique === 2 ? plainEscape : escape;
for (var nItem = 0; nItem < oTarget.elements.length; nItem++) {
oField = oTarget.elements[nItem];
if (!oField.hasAttribute("name")) { continue; }
sFieldType = oField.nodeName.toUpperCase() === "INPUT" ? oField.getAttribute("type").toUpperCase() : "TEXT";
if (sFieldType === "FILE" && oField.files.length > 0) {
if (this.technique === 3) {
/* enctype is multipart/form-data */
for (nFile = 0; nFile < oField.files.length; nFile++) {
oFile = oField.files[nFile];
oSegmReq = new FileReader();
/* (custom properties:) */
oSegmReq.segmentIdx = this.segments.length;
oSegmReq.owner = this;
/* (end of custom properties) */
oSegmReq.onload = pushSegment;
this.segments.push("Content-Disposition: form-data; name=\"" + oField.name + "\"; filename=\""+ oFile.name + "\"\r\nContent-Type: " + oFile.type + "\r\n\r\n");
this.status++;
oSegmReq.readAsBinaryString(oFile);
}
} else {
/* enctype is application/x-www-form-urlencoded or text/plain or method is GET: files will not be sent! */
for (nFile = 0; nFile < oField.files.length; this.segments.push(fFilter(oField.name) + "=" + fFilter(oField.files[nFile++].name)));
}
} else if ((sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") || oField.checked) {
/* field type is not FILE or is FILE but is empty */
!(oField.value || oField.defaultValue)||this.segments.push(
this.technique === 3 ? /* enctype is multipart/form-data */
"Content-Disposition: form-data; name=\"" + oField.name + "\"\r\n\r\n" + (oField.value || oField.defaultValue) + "\r\n"
: /* enctype is application/x-www-form-urlencoded or text/plain or method is GET */
fFilter(oField.name) + "=" + fFilter(oField.value)
);
}
console.log([oField,this.segments]);
}
return processStatus(this);
}
return function (oFormElement) {
if (!oFormElement.action) { return; }
return new SubmitRequest(oFormElement);
};
})();
<?php
class upload
{
var $directory_name;
var $max_filesize = 2000000;
var $error;
var $mimetypes = array('image/cgm','image/example','image/fits','image/g3fax','image/gif','image/ief','image/jp2','image/jpeg','image/jpm','image/jpx','image/ktx','image/naplps','image/png','image/prs.btif','image/prs.pti','image/pwg-raster','image/svg+xml','image/t38','image/tiff','image/tiff-fx','image/vnd.adobe.photoshop','image/vnd.airzip.accelerator.azv','image/vnd.cns.inf2','image/vnd.dece.graphic','image/vnd.djvu','image/vnd.dwg','image/vnd.dxf','image/vnd.dvb.subtitle','image/vnd.fastbidsheet','image/vnd.fpx','image/vnd.fst','image/vnd.fujixerox.edmics-mmr','image/vnd.fujixerox.edmics-rlc','image/vnd.globalgraphics.pgb','image/vnd.microsoft.icon','image/vnd.mix','image/vnd.ms-modi','image/vnd.net-fpx','image/vnd.radiance','image/vnd.sealed.png','image/vnd.sealedmedia.softseal.gif','image/vnd.sealedmedia.softseal.jpg','image/vnd.svf','image/vnd.wap.wbmp','image/vnd.xiff');
var $user_tmp_name;
var $user_file_name;
var $user_file_size;
var $user_file_type;
var $user_full_name;
function set_directory($dir_name =".")
{
$this->directory_name = $dir_name;
}
function set_max_size($max_file = 0)
{
$this->max_filesize = $max_file;
//return $this->max_filesize;
}
function error()
{
return $this->error;
}
function is_ok()
{
if(isset($this->error))
return FALSE;
else
return TRUE;
}
function set_tmp_name($temp_name)
{
$this->user_tmp_name = $temp_name;
}
function set_file_size($file_size)
{
$this->user_file_size = $file_size;
}
function set_file_type($file_type)
{
$this->user_file_type = $file_type;
}
function set_file_name($file)
{
$this->user_file_name = $file;
$this->user_full_name = $this->directory_name.DIRECTORY_SEPARATOR.$this->user_file_name;
}
function start_copy()
{
if(!isset($this->user_file_name))
$this->error = "You must define filename!";
if ($this->user_file_size <= 0)
$this->error = 'File size error (0):' . $this->user_file_size . 'KB <br/>';
if ($this->user_file_size > $this->max_filesize)
$this->error = 'File size error (1):' . $this->user_file_size . '/'.$this->max_filesize.'KB<br>';
if(@$mimetypes[$this->user_file_type])
$this->error = "File type error (2)";
$filename = basename($this->user_file_name);
if (!empty($this->directory_name))
$destination = $this->user_full_name;
else
$destination = $filename;
if(file_exists($destination))
$this->error = "File already exists (3): ".$this->user_file_name;
if (!isset($this->error))
{
if(!is_uploaded_file($this->user_tmp_name))
$this->error = "File " . $this->user_tmp_name . " is not uploaded correctly.";
if (!move_uploaded_file ($this->user_tmp_name,$destination))
$this->error = "Impossible to copy " . $this->user_file_name . " from your folder to destination directory.";
}
}
}
if (isset($_FILES['file'])) {
$uploaded = new upload;
//set Max Size
$uploaded->set_max_size(350000);
//Set Directory
$uploaded->set_directory(getcwd().DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'images'); // TODO: Change structure of the dyrectory
//Set Temp Name for upload.
$uploaded->set_tmp_name($_FILES['file']['tmp_name']);
//Set file size
$uploaded->set_file_size($_FILES['file']['size']);
//set file type
$uploaded->set_file_type($_FILES['file']['type']);
//set file name
$uploaded->set_file_name($_FILES['file']['name']);
//start copy process
$uploaded->start_copy();
if($uploaded->is_ok()){
echo "Upload of ".$_FILES['file']['name']." is complete";
}else{
echo $uploaded->error();
}
}elseif(isset($_POST['files'])){
echo '(['.JSON_encode(array(
'post' => $_POST,
'get' => $_GET,
'files' => $_FILES
)).",\n";
// file_put_contents('img.png', base64_decode($base64string));
echo "{\n";
foreach ( $_POST['files'] as $name => $file ){
list($type, $data) = explode(';', $file);
list(,$data) = explode(',', $data);
list(,$type) = explode(':', $type);
echo '"name":"'.$name.'",'."\n";
echo '"type":"'.$type.'",'."\n";
//echo '"data":"'.$data.'",'."\n";
$data = base64_decode($data);
$basepath = getcwd().DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'images';
$fullpath = $basepath.DIRECTORY_SEPARATOR.$name;
if(!file_exists($fullpath))
file_put_contents($fullpath, $data);
else
echo '"error":"File exists"';
}
echo "}]);\n";
/*
$data = 'data:image/png;base64,AAAFBfj42Pj4';
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
file_put_contents('/tmp/image.png', $data);
*/
}else{
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Upload form</title>
<style>
html,body{
width:100%;
height:100%;
margin:0;
padding:0;
}
#dropzone {
width:100%;
height: 100%;
}
#dropzone img{
width: 100px;
vertical-align: middle;
padding: .2em;
border: gainsboro solid 1px;
border-radius: .2em;
box-shadow: .1em .1em .2em rgba(128,128,128,.5);
margin: .2em;
}
#dropzone.hover {
background-color: rgba(128,128,128,.1);
}
</style>
</head>
<body>
<form id="dropzone" action="/upload.php" enctype="multipart/form-data" method="POST" onsubmit="javascript:AJAXSubmit(this); return false;">
<input type="file" multiple name="files[]"/>
<input type="submit"/>
<hr/>
</form>
<script src="upload.js"></script>
<script>
//var doc = document.documentElement;
var doc = document.getElementById('dropzone');
doc.ondragover = function () {
this.className = 'hover';
return false;
};
doc.ondragend =
//doc.ondragleave =
function () {
doc.className = '';
return false;
};
doc.ondrop = function (event) {
maxFileSize = 2048000; // 10MB
event.preventDefault && event.preventDefault();
this.className = '';
[].forEach.call(event.dataTransfer.files,function(file,n){
if (file.size > maxFileSize) {
alert('Файл '+file.name+' слишком большой!');
return false;
}
if (typeof FileReader !== "undefined" && (/image/i).test(file.type)) {
reader = new FileReader();
reader.onload = (function (d,f) {
return function (evt) {
//console.log([d,f,this,evt,doc,img]);
var img = document.createElement('img');
img.src = evt.target.result;
img.alt = f.name;
doc.appendChild(img);
var input = document.createElement('input');
input.setAttribute('type','hidden');
//input.setAttribute('type','file');
input.setAttribute('data-size',f.size);
input.setAttribute('data-lastModifiedDate',f.lastModifiedDate);
input.setAttribute('data-webkitRelativePath',f.webkitRelativePath);
//input.setAttribute('name','images['+(n+1)+']');
input.setAttribute('name','files['+f.name+']');
//input.setAttribute('value',f.name);
input.setAttribute('value', evt.target.result);
doc.appendChild(input);
};
}(this,file));
reader.readAsDataURL(file);
}
});
};
</script>
</body>
</html>
<?php } ?>
@iegik

iegik commented Jul 28, 2013

Copy link
Copy Markdown
Author

Known issues: When drag'n'drop files - file names with non-ascii symbols will be corrupted, need to fix that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment