Can I kindly ask for a good working example of HTML5 File Drag and Drop implementation? The source code should work if drag and drop is performed from external application(Windows Explorer) to browser window. It should work on as many browsers as possible.
I would like to ask for a sample code with good explanation. I do not wish to use third party libraries, as I will need to modify the code according to my needs. The code should be based on HTML5 and JavaScript. I do not wish to use JQuery.
I spent the whole day searching for good source of material, but surprisingly, I did not find anything good. The examples I found worked for Mozilla but did not work for Chrome.
Here is a dead-simple example. It shows a red square. If you drag an image over the red square it appends it to the body. I've confirmed it works in IE11, Chrome 38, and Firefox 32. See the Html5Rocks article for a more detailed explanation.
var dropZone = document.getElementById('dropZone');
// Optional. Show the copy icon when dragging over. Seems to only work for chrome.
dropZone.addEventListener('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
// Get file data on drop
dropZone.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
var files = e.dataTransfer.files; // Array of all files
for (var i=0, file; file=files[i]; i++) {
if (file.type.match(/image.*/)) {
var reader = new FileReader();
reader.onload = function(e2) {
// finished reading file data.
var img = document.createElement('img');
img.src= e2.target.result;
document.body.appendChild(img);
}
reader.readAsDataURL(file); // start reading the file data.
}
}
});
<div id="dropZone" style="width: 100px; height: 100px; background-color: red"></div>
The accepted answer provides an excellent link for this topic; however, per SO rules, pure link answers should be avoided since the links can rot at any time. For this reason, I have taken the time to summarize the content of the link for future readers.
Getting Started
Prior to implementing a method to upload files to your website, you should ensure that the browsers you choose to support will be capable of fully supporting the File API. You can test this quickly with the snippet of Javascript below:
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
} else {
alert('The File APIs are not fully supported in this browser.');
}
You can modify the snippet above to meet your needs of course.
Form Input
The most common way to upload a file is to use the standard <input type="file"> element. JavaScript returns the list of selected File objects as a FileList.
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
Drag and Drop
Making simple modifications to the snippet above allows us to provide drag and drop support.
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files; // FileList object.
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}
// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
#drop_zone {
min-height: 10em;
background: #eee;
}
<div id="drop_zone">Drop files here</div>
<output id="list"></output>
Reading Files
Now you've obtained a reference to the File, you can instantiate a FileReader to read its contents into memory. When the load completes the onload event is fired and its result attribute can be used to access the file data. Feel free to look at the references for FileReader to cover the four available options for reading a file.
The example below filters out images from the user's selection, calls reader.readAsDataURL() on the file, and renders a thumbnail by setting the src attribute to a data URL.
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
.thumb {
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
Slicing
In some cases reading the entire file into memory isn't the best option. For example, say you wanted to write an async file uploader. One possible way to speed up the upload would be to read and send the file in separate byte range chunks. The server component would then be responsible for reconstructing the file content in the correct order.
The following example demonstrates reading chunks of a file. Something worth noting is that it uses the onloadend and checks the evt.target.readyState instead of using the onload event.
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
document.getElementById('byte_range').textContent =
['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
#byte_content {
margin: 5px 0;
max-height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
#byte_range { margin-top: 5px; }
<input type="file" id="files" name="file" /> Read bytes:
<span class="readBytesButtons">
<button data-startbyte="0" data-endbyte="4">1-5</button>
<button data-startbyte="5" data-endbyte="14">6-15</button>
<button data-startbyte="6" data-endbyte="7">7-8</button>
<button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>
Monitoring Progress
One of the nice things that we get for free when using async event handling is the ability to monitor the progress of the file read; useful for large files, catching errors, and figuring out when a read is complete.
The onloadstart and onprogress events can be used to monitor the progress of a read.
The example below demonstrates displaying a progress bar to monitor the status of a read. To see the progress indicator in action, try a large file or one from a remote drive.
var reader;
var progress = document.querySelector('.percent');
function abortRead() {
reader.abort();
}
function errorHandler(evt) {
switch(evt.target.error.code) {
case evt.target.error.NOT_FOUND_ERR:
alert('File Not Found!');
break;
case evt.target.error.NOT_READABLE_ERR:
alert('File is not readable');
break;
case evt.target.error.ABORT_ERR:
break; // noop
default:
alert('An error occurred reading this file.');
};
}
function updateProgress(evt) {
// evt is an ProgressEvent.
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
// Increase the progress bar length.
if (percentLoaded < 100) {
progress.style.width = percentLoaded + '%';
progress.textContent = percentLoaded + '%';
}
}
}
function handleFileSelect(evt) {
// Reset progress indicator on new file selection.
progress.style.width = '0%';
progress.textContent = '0%';
reader = new FileReader();
reader.onerror = errorHandler;
reader.onprogress = updateProgress;
reader.onabort = function(e) {
alert('File read cancelled');
};
reader.onloadstart = function(e) {
document.getElementById('progress_bar').className = 'loading';
};
reader.onload = function(e) {
// Ensure that the progress bar displays 100% at the end.
progress.style.width = '100%';
progress.textContent = '100%';
setTimeout("document.getElementById('progress_bar').className='';", 2000);
}
// Read in the image file as a binary string.
reader.readAsBinaryString(evt.target.files[0]);
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
#progress_bar {
margin: 10px 0;
padding: 3px;
border: 1px solid #000;
font-size: 14px;
clear: both;
opacity: 0;
-moz-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-webkit-transition: opacity 1s linear;
}
#progress_bar.loading {
opacity: 1.0;
}
#progress_bar .percent {
background-color: #99ccff;
height: auto;
width: 0;
}
<input type="file" id="files" name="file" />
<button onclick="abortRead();">Cancel read</button>
<div id="progress_bar"><div class="percent">0%</div></div>
Look into ondragover event. You could simply have a inside of a div that is hidden until the ondragover event fires a function that will show the div with the in it, thus letting the user drag and drop the file. Having an onchange declaration on the would let you automatically call a function (such as upload) when a file is added to the input. Make sure that the input allows for multiple files, as you have no control over how many they are going to try and drag into the browser.
This technique works very well, but if you want a binary blob rather than just to put the dragged image in an html img element, you'll need to use the 'fetch' function twice.
Related
i working on this code that the objective is to: check if is a PNG, check if is 256X256, and transform img to base64 to upload to the server.
so if i select a 256 x 256 img it's loads but,if i load another img that is not a 256 x 256 after selecting a 256 x 256 it's loads and i don't know why!
Video Showing
How can i resolve it?
function isFileImage(file) {
const acceptedImageTypes = ['image/png'];
return file && acceptedImageTypes.includes(file['type'])
}
function importFileandPreview() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
if (file) {
//read img
reader.readAsDataURL(file);
//verify type
var text = file.type;
if (text === "image/png") {
//load img
reader.addEventListener("load", function () {
//put img on <img> src
//console logs
//console.log(preview);
//console.log("pre_nat_height:"+preview.naturalHeight);
// console.log("pre_nat_width:"+preview.naturalWidth);
//technically check if img is 256 x 256
var old = preview.src;
preview.src = reader.result;
if(preview.naturalHeight === 256 && preview.naturalWidth === 256){
//create a hidden input (works but value is not from last img)
var element = document.getElementById("imga");
if(typeof(element) != 'undefined' && element != null){
document.getElementById("imga").remove();
}
input = document.createElement('input');
input.setAttribute("type","hidden");
input.setAttribute("id","imga");
input.setAttribute("name","img")
input.setAttribute("value",preview.src);
document.getElementById('count').appendChild(input);
delete preview;
}
//else if img is not 256 x 256
else {
preview.src = old;
alert("Must be a PNG and have 256px X 256px!");
delete preview;
}
}, false);// i don't know why false but ye
}
}
}
<input type="file" id="file" accept="image/PNG" onchange="importFileandPreview()"><br>
<img src=" data:image/png;base64,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" height="256" width="256">
<form id="count">
</form>
tl;dr: You need to perform the check against the natural dimensions of the image inside the handler for the preview's load event.
The problem you're facing is a consequence of bad timing rather than poor logic. More specifically, it lies in that you set the new src of your preview and then check against the loaded image's natural dimensions synchronously.
This approach is wrong because an image loads asynchronously and, therefore, your code doesn't wait for it to load before proceeding with your check. As a result, when, after selecting a valid image, you select an invalid one, you're still checking against the dimensions of the former as the latter hasn't yet loaded.
To correct this error, you have to perform your check inside the handler for the preview's load event, just as shown below.
Working Snippet:
(I've rewritten the function to make it easier to read)
function isFileImage (file) {
const acceptedImageTypes = ["image/png"];
return file && acceptedImageTypes.includes(file["type"])
}
function importFileandPreview () {
var preview = document.querySelector("img");
var file = document.querySelector("input[type=file]").files[0];
var reader = new FileReader();
/* Terminate the function prematurely if the file isn't an image. */
if (!isFileImage(file)) return;
/* Load the file into the reader. */
reader.readAsDataURL(file);
/* Set the 'load' event of the reader. */
reader.addEventListener("load", function () {
/* Create a temporary image to use for the check to avoid flashing. */
var tempPreview = new Image();
/* Set the 'load' event of the temporary preview. */
tempPreview.addEventListener("load", function () {
/* Check whether the selected image isn't 256x256 pixels. */
if (this.naturalHeight != 256 || this.naturalWidth != 256) {
/* Alert the user. */
alert("Must be a PNG and have 256px X 256px!");
/* Restore the default src to the preview. */
preview.src = preview.dataset.defaultSrc;
/* Terminate the function prematurely. */
return;
}
/* Set the result of the reader as the source of the preview. */
preview.src = reader.result;
/* Save the image to the form. */
saveImageToInput(reader.result);
});
/* Set the result of the reader as the source of the image. */
tempPreview.src = reader.result;
});
/* Save the default image in a data-* attribute to use again if needed. */
preview.dataset.defaultSrc = preview.dataset.defaultSrc || preview.src;
}
function saveImageToInput (image) {
/* Find the hidden input. */
var input = document.getElementById("imga");
/* Check whether the input doesn't exist. */
if (!input) {
/* Create a new hidden input. */
input = document.createElement("input");
input.setAttribute("id", "imga");
input.setAttribute("name", "img");
input.setAttribute("type", "hidden");
/* Place the input in the form. */
document.getElementById("count").appendChild(input);
}
/* Save the image as the input's value. */
input.setAttribute("value", image);
}
<input type="file" id="file" accept="image/PNG" onchange="importFileandPreview()"><br>
<img src=" data:image/png;base64,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" height="256" width="256">
<form id="count">
</form>
Notes:
It's a good idea to use a temporary preview to check if the selected image fulfils your criteria because, if you load it in the visible preview and then alert the user, the loaded image will show.
delete preview: Don't do this. Variables in JavaScript aren't supposed to be deleted like this.
The third argument passed to addEventListener determines whether the event is caught in the bubbling or the capturing phase. By default, it's false, so you can omit it.
I'm trying to add a multiple image up-loader which returns a JavaScript array that is populated by the user selecting images. I will be using this image up-loader with other input form elements which will all submit together, in this case i'm not using AJAX. The maximum file upload size is 2MB. The JavaScript array contains the base 64 encoded image with all the details including size, type etc.
I have used $('#j_son').val(JSON.stringify(AttachmentArray)); outside the array to populate the hidden input field everytime the array is populated (input unhidden to show JSON string). Lightweight Multiple File Upload with Thumbnail Preview using HTML5 and Client Side Scripts
On submit I will use PHP to decode the new JSON string and and put the multiple images in a folder called uploads.
The problem I am facing is that selecting image attachments larger than 200 KB seem to slow the output of images inside the div container and the JSON string inside the hidden input field and anything to large will cause "aw snap" error inside chrome and crash the browser, I don't know where I'm going wrong. I also have a click event that when the user clicks X remove button and the hidden input field is repopulated with the updated JSON array, this to is really slow and crashes if the files are to large. The PHP side of things has no problem decoding the JSON string it seems to either fall on the JavaScript code or the extra functionality I have added at the bottom of the script. Is there a way to stop this from happening? I have added the full code including the PHP if anybody wants to test it.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<style>
/*Copied from bootstrap to handle input file multiple*/
.btn {
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 14px;
font-weight: normal;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
}
/*Also */
.btn-success {
border: 1px solid #c5dbec;
background: #D0E5F5;
font-weight: bold;
color: #2e6e9e;
}
/* This is copied from https://github.com/blueimp/jQuery-File-
Upload/blob/master/css/jquery.fileupload.css */
.fileinput-button {
position: relative;
overflow: hidden;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
font-size: 200px;
direction: ltr;
cursor: pointer;
}
.thumb {
height: 80px;
width: 100px;
border: 1px solid #000;
}
ul.thumb-Images li {
width: 120px;
float: left;
display: inline-block;
vertical-align: top;
height: 120px;
}
.img-wrap {
position: relative;
display: inline-block;
font-size: 0;
}
.img-wrap .close {
position: absolute;
top: 2px;
right: 2px;
z-index: 100;
background-color: #D0E5F5;
padding: 5px 2px 2px;
color: #000;
font-weight: bolder;
cursor: pointer;
opacity: .5;
font-size: 23px;
line-height: 10px;
border-radius: 50%;
}
.img-wrap:hover .close {
opacity: 1;
background-color: #ff0000;
}
.FileNameCaptionStyle {
font-size: 12px;
}
</style>
<script type="text/javascript" src="scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
//I added event handler for the file upload control to access the files
properties.
document.addEventListener("DOMContentLoaded", init, false);
//To save an array of attachments
var AttachmentArray = [];
$('#j_son').val(JSON.stringify(AttachmentArray));
//counter for attachment array
var arrCounter = 0;
//to make sure the error message for number of files will be shown only
one time.
var filesCounterAlertStatus = false;
//un ordered list to keep attachments thumbnails
var ul = document.createElement('ul');
ul.className = ("thumb-Images");
ul.id = "imgList";
function init() {
//add javascript handlers for the file upload event
document.querySelector('#files').addEventListener('change',
handleFileSelect, false);
}
//the handler for file upload event
function handleFileSelect(e) {
//to make sure the user select file/files
if (!e.target.files) return;
//To obtaine a File reference
var files = e.target.files;
// Loop through the FileList and then to render image files as
thumbnails.
for (var i = 0, f; f = files[i]; i++) {
//instantiate a FileReader object to read its contents into
memory
var fileReader = new FileReader();
// Closure to capture the file information and apply validation.
fileReader.onload = (function (readerEvt) {
return function (e) {
//Apply the validation rules for attachments upload
ApplyFileValidationRules(readerEvt)
//Render attachments thumbnails.
RenderThumbnail(e, readerEvt);
//Fill the array of attachment
FillAttachmentArray(e, readerEvt)
};
})(f);
// Read in the image file as a data URL.
// readAsDataURL: The result property will contain the
//file/blob's data encoded as a data URL.
// More info about Data URI scheme
//https://en.wikipedia.org/wiki/Data_URI_scheme
fileReader.readAsDataURL(f);
}
document.getElementById('files').addEventListener('change',
handleFileSelect, false);
}
//To remove attachment once user click on x button
jQuery(function ($) {
$('div').on('click', '.img-wrap .close', function () {
var id = $(this).closest('.img-wrap').find('img').data('id');
//to remove the deleted item from array
var elementPos = AttachmentArray.map(function (x) { return
x.FileName; }).indexOf(id);
if (elementPos !== -1) {
AttachmentArray.splice(elementPos, 1);
}
//to remove image tag
$(this).parent().find('img').not().remove();
//to remove div tag that contain the image
$(this).parent().find('div').not().remove();
//to remove div tag that contain caption name
$(this).parent().parent().find('div').not().remove();
//to remove li tag
var lis = document.querySelectorAll('#imgList li');
for (var i = 0; li = lis[i]; i++) {
if (li.innerHTML == "") {
li.parentNode.removeChild(li);
}
}
});
}
)
//Apply the validation rules for attachments upload
function ApplyFileValidationRules(readerEvt)
{
//To check file type according to upload conditions
if (CheckFileType(readerEvt.type) == false) {
alert("The file (" + readerEvt.name + ") does not match the
upload conditions, You can only upload jpg/png/gif files");
e.preventDefault();
return;
}
//To check file Size according to upload conditions
if (CheckFileSize(readerEvt.size) == false) {
alert("The file (" + readerEvt.name + ") does not match the
upload conditions, The maximum file size for uploads should not
exceed 300 KB");
e.preventDefault();
return;
}
//To check files count according to upload conditions
if (CheckFilesCount(AttachmentArray) == false) {
if (!filesCounterAlertStatus) {
filesCounterAlertStatus = true;
alert("You have added more than 10 files. According to
upload conditions you can upload 10 files maximum");
}
e.preventDefault();
return;
}
}
//To check file type according to upload conditions
function CheckFileType(fileType) {
if (fileType == "image/jpeg") {
return true;
}
else if (fileType == "image/png") {
return true;
}
else if (fileType == "image/gif") {
return true;
}
else if (fileType == "image/jpg") {
return true;
}
else {
return false;
}
return true;
}
//To check file Size according to upload conditions
function CheckFileSize(fileSize) {
if (fileSize < 2000000) {
return true;
}
else {
return false;
}
return true;
}
//To check files count according to upload conditions
function CheckFilesCount(AttachmentArray) {
//Since AttachmentArray.length return the next available index in
//the array,
//I have used the loop to get the real length
var len = 0;
for (var i = 0; i < AttachmentArray.length; i++) {
if (AttachmentArray[i] !== undefined) {
len++;
}
}
//To check the length does not exceed 10 files maximum
if (len > 9) {
return false;
}
else
{
return true;
}
}
//Render attachments thumbnails.
function RenderThumbnail(e, readerEvt)
{
var li = document.createElement('li');
ul.appendChild(li);
li.innerHTML = ['<div class="img-wrap"> <span class="close">×
</span>' +
'<img class="thumb" src="', e.target.result, '" title="',
escape(readerEvt.name), '" data-id="',
readerEvt.name, '"/>' + '</div>'].join('');
var div = document.createElement('div');
div.className = "FileNameCaptionStyle";
li.appendChild(div);
div.innerHTML = [readerEvt.name].join('');
document.getElementById('Filelist').insertBefore(ul, null);
}
//Fill the array of attachment
function FillAttachmentArray(e, readerEvt)
{
AttachmentArray[arrCounter] =
{
AttachmentType: 1,
ObjectType: 1,
FileName: readerEvt.name,
FileDescription: "Attachment",
NoteText: "",
MimeType: readerEvt.type,
Content: e.target.result.split("base64,")[1],
FileSizeInBytes: readerEvt.size,
};
arrCounter = arrCounter + 1;
//THIS IS THE PART I ADDED TO POPULATE THE HIDDEN INPUT FIELD
$('#j_son').val(JSON.stringify(AttachmentArray));
}
//THIS IS TO UPDATE THE INPUT FIELD WHEN A FILE IS REMOVED
$(document).on('click', '.close', function(){
var myString = JSON.stringify(AttachmentArray);
$('#j_son').val(myString);
});
</script>
</head>
<body>
<div>
<label style="font-size: 14px;">
<span style='color:navy;font-weight:bold'>Attachment Instructions :
</span>
</label>
<ul>
<li>
Allowed only files with extension (jpg, png, gif)
</li>
<li>
Maximum number of allowed files 10 with 2 MB for each
</li>
<li>
you can select files from different folders
</li>
</ul>
<form method="POST" action="" enctype="multipart/form-data">
<span class="btn btn-success fileinput-button">
<span>Select Attachment</span>
<input type="file" name="files[]" id="files" multiple
accept="image/jpeg, image/jpg image/png, image/gif,"><br />
</span>
<!--input field to be populated by the array-->
<input type="text" name="j_son" id="j_son" style="width: 500px;">
<!--Submit and post to get decoded JSON string-->
<button type="submit" id="image_post" name="post_it">Submit</button>
</form>
<output id="Filelist"></output>
</div>
<?php
if(isset($_POST['post_it']))
{
//other input fields
$file = $_POST['j_son'];
$tempData = html_entity_decode($file);
$cleanData = json_decode($tempData, true);
foreach($cleanData as $p)
{
echo $p['Content']."</br>";
//insert code to uploads folder
}
}
?>
</body>
</html>
-- edit --
This may be because of a known issue in chrome. Try using a blob as recommended in this post
How can javascript upload a blob?
function uploadAudio( blob ) {
var reader = new FileReader();
reader.onload = function(event){
var fd = {};
fd["fname"] = "test.wav";
fd["data"] = event.target.result;
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
dataType: 'text'
}).done(function(data) {
console.log(data);
});
};
reader.readAsDataURL(blob);
}
-- /edit --
ok it seems like you are adding an onChange event listener multiple times to the "files" id. Once in the init and once every time the handleFileSelect function is called. This could for sure be your slowdown problem.
Also, if you are going to have a file upload size that maxes out at 2MB you should set this in your PHP file using upload_max_filesize and also set post_max_size.
ini_set('upload_max_filesize', '2M');
ini_set('post_max_size', '2M');
from php.net:
upload_max_filesize
The maximum size of an uploaded file.
post_max_size
Sets max size of post data allowed. This setting also affects file upload. To upload large files, this value must be larger than upload_max_filesize. Generally speaking, memory_limit should be larger than post_max_size. When an integer is used, the value is measured in bytes.
Also if your upload ends up timing out you might also want to extend the execution time by using max_input_time or max_execution time though I think that max_input_time should be enough.
ini_set('max_input_time', 300);
ini_set('max_execution_time', 300);
max_input_time
This sets the maximum time in seconds a script is allowed to parse input data, like POST and GET. Timing begins at the moment PHP is invoked at the server and ends when execution begins. The default setting is -1, which means that max_execution_time is used instead. Set to 0 to allow unlimited time.
max_execution_time
This sets the maximum time in seconds a script is allowed to run before it is terminated by the parser. This helps prevent poorly written scripts from tying up the server. The default setting is 30. When running PHP from the command line the default setting is 0.
This needs to be added at the top of your PHP file before other output.
Are there any Fabric.JS Wizards out there?
I've done my fair research and I can't seem to find much of an explanation on how to add an image to the fabric.JS canvas.
User Journey:
a) User uploads an image from an input file type button.
b) As soon as they have selected an image from their computer I want to place it into the users canvas.
So far I've got to storing the image into an expression, this is my code below:
scope.setFile = function(element) {
scope.currentFile = element.files[0];
var reader = new FileReader();
/**
*
*/
reader.onload = function(event) {
// This stores the image to scope
scope.imageSource = event.target.result;
scope.$apply();
};
// when the file is read it triggers the onload event above.
reader.readAsDataURL(element.files[0]);
};
My HTML/Angular:
<label class="app-file-input button">
<i class="icon-enter"></i>
<input type="file"
id="trigger"
onchange="angular.element(this).scope().setFile(this)"
accept="image/*">
</label>
If you haven't guessed yet I am using a MEAN stack. Mongoose, Express, Angular and Node.
The scope imageSource is what the image is store in. I've read this SO
and it talks about pushing the image to the Image object with my result, and then pass it to the fabric.Image object. Has anyone done a similar thing that they can help me with?
Thanks in advance
**** UPDATE ****
Directive defines the canvas variable:
var canvas = new fabric.Canvas(attrs.id, {
isDrawingMode: true
});
Upload image from computer with Fabric js.
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 0, top: 0, angle: 00,width:100, height:100}).scale(0.9);
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({format: 'png', quality: 0.8});
});
};
reader.readAsDataURL(file);
});
canvas{
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<input type="file" id="file"><br />
<canvas id="canvas" width="450" height="450"></canvas>
once you have a dataURL done, you can do either:
reader.onload = function(event) {
// This stores the image to scope
fabric.Image.fromURL(event.target.result, function(img) {
canvas.add(img);
});
scope.$apply();
};
Or you put on your image tag an onload event where you do:
var img = new fabric.Image(your_img_element);
canvas.add(img);
This is for drag and drop from desktop using the dataTransfer interface.
canvas.on('drop', function(event) {
// prevent the file to open in new tab
event.e.stopPropagation();
event.e.stopImmediatePropagation();
event.e.preventDefault();
// Use DataTransfer interface to access the file(s)
if(event.e.dataTransfer.files.length > 0){
var files = event.e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (f.type.match('image.*')) {
// Read the File objects in this FileList.
var reader = new FileReader();
// listener for the onload event
reader.onload = function(evt) {
// put image on canvas
fabric.Image.fromURL(evt.target.result, function(obj) {
obj.scaleToHeight(canvas.height);
obj.set('strokeWidth',0);
canvas.add(obj);
});
};
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
}
});
Resources
https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop
I need to show upload image before upload using jquery but in chrome path shown fake path like this:
C:\fakepath\myImage.jpg
and in firefox it's shown only file name:
myImage.jpg
so how can me preview my image file before uploading
<input type="file">
<img src="" class="preview" />
if that is impossible.. what about HTML5?
I don't know of a jQuery function (sorry), but it is possible with HTML5, and most browsers support this HTML5 function. I found a piece of code in HTML5rocks (1):
<style>
.thumb {
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}
</style>
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
Good luck :)
(1) HTML5rocks - Reading Files: http://www.html5rocks.com/en/tutorials/file/dndfiles/
You can't. You need to upload image using ajax, for example, return image url and finally display it.
The idea is to take an image from a user's machine and allow them to display the image in a webpage. I do not want to send the image back to the server.
An upload button will exist. It should just update the page content dynamically.
Can this be done with HTML5 localstorage or anything?
FileReader is capable of doing this. Here's sample code:
<input type="file" id="files" name="files[]" multiple />
<img id="image" />
<script>
function onLoad(evt) {
/* do sth with evt.target.result - it image in base64 format ("data:image/jpeg;base64,....") */
localStorage.setItem('image', evt.target.result);
document.getElementById('image').src = evt.target.result;
};
function handleFileUpload(evt) {
var files = evt.target.files; // FileList object
for (var i = 0; i < files.length; i++) {
var f = files[i];
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
reader.onload = onLoad;
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileUpload, false);
var image = localStorage.getItem('image');
if (image !== null) {
document.getElementById('image').src = image;
}
</script>
Yeah absolutely, providing you have a cutting edge browser (Chrome or Firefox).
You want to use FileReader and readAsDataURL(). Take a look at the third example in this tutorial:
http://www.html5rocks.com/en/tutorials/file/dndfiles/