I am trying to upload an image using AJAX. I have the local URL of my image
and I want to pass that image as a file to the web service to upload.
Suppose i have the local file URL as : file:///accounts/1000/shared/camera/IMG_00000322.jpg
Now using AJAX I want to pass this to webservice,
What will be the best way to do this? I also want show the progress while uploading
Using php in server side.
uploadImage : function(myImageUrl,chatId){
var formData = new FormData();
formData.append("chatId", chatId);
formData.append("fileimage", myImageUrl);
$.ajax(
{
type:"POST",
url:"http://suresh.sp.in/butler/public/uploadimage/getimage",
contentType:"image/png",
dataType:"json",
data:formData,
success:function(uploaded){
console.info(uploaded.status);
},
error:function(error){
console.info(error);
}
});
}
I used that snippet on several of my websites, it handles Multiples files upload, drag and drop, and a progress bar.
HTML
You will need a container to drop your batch of files, in our case it will be #output, and a list of files.
JS
First we will push the dataTransfer to jQuery's event and bind the drop event.
$(document).ready(function(){
// We add the dataTransfer special property to our jQuery event
$.event.props.push("dataTransfer");
// We bind events for drag and drop
$('#output').bind({
"dragenter dragexit dragover" : do_nothing,
drop : drop
});
});
// stop event propagation
function do_nothing(evt){
evt.stopPropagation();
evt.preventDefault();
}
Then we build our update progress function
// Progress bar update function
function update_progress(evt,fic) {
var id_tmp=fic.size;
//id_tmp help us keep track of which file is uploaded
//right now it uses the filesize as an ID: script will break if 2 files have the
// same size
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
if (percentLoaded <= 100) {
$('#'+id_tmp+' .percent').css('width', percentLoaded + '%');
$('#'+id_tmp+' .percent').html(percentLoaded + '%');
}
}
}
Last but not least our drop function
function drop(evt){
do_nothing(evt);
var files = evt.dataTransfer.files;
// Checking if there are files
if(files.length>0){
for(var i in files){
// if its really a file
if(files[i].size!=undefined) {
var fic=files[i];
// We add a progress listener
xhr = jQuery.ajaxSettings.xhr();
if(xhr.upload){
xhr.upload.addEventListener('progress', function (e) {
update_progress(e,fic);
},false);
}
provider=function(){ return xhr; };
// We build our FormData object
var fd=new FormData;
fd.append('fic',fic);
// For each file we build and Ajax request
$.ajax({
url:'/path/to/save_fic.php',
type: 'POST',
data: fd,
xhr:provider,
processData:false,
contentType:false,
complete:function(data){
//on complete we set the progress to 100%
$('#'+data.responseText+' .percent').css('width', '100%');
$('#'+data.responseText+' .percent').html('100%');
}
});
// for each file we setup a progress bar
var id_tmp=fic.size;
$('#output').after('<div class="progress_bar loading" id="'+id_tmp+'"><div class="percent">0%</div></div>');
$('#output').addClass('output_on');
// We add our file to the list
$('#output-listing').append('<li>'+files[i].name+'</li>');
}
}
}
}
That method doesn't work in IE9 or below.
Hope it helped!
Source(in french)
Some infos on progress tracking using XMLHttpRequest
Some infos on the datatransfer prop
EDIT:
PHP
From the server side you can handle the files normally using $_FILES etc...
In order to set the progress to 100% in the complete function your php script must echo the filesize.
Related
I want to do a sheduled task for every day.I have multiple servers and i want to automate the upload of html file to my other servers.In this case i have on the same folder my html and my script.js.Im currently using ajax to upload the html file but i want to do that without interference.Here is my javascript.
$(function(){
$("#drop-box").click(function(){
$("#upl").click();
});
// To prevent Browsers from opening the file when its dragged and dropped on to the page
$(document).on('drop dragover', function (e) {
e.preventDefault();
});
// Add events
$('input[type=file]').on('change', fileUpload);
// File uploader function
function fileUpload(event){
$("#drop-box").html("<p>"+event.target.value+" uploading...</p>");
files = event.target.files;
var data = new FormData();
var error = 0;
for (var i = 0; i < files.length; i++) {
var file = files[i];
console.log(file.type);
if(!file.type.match('html.*')) {
$("#drop-box").html("<p> Html only. Select another file</p>");
error = 1;
}else if(file.size > 1048576){
$("#drop-box").html("<p> Too large Payload. Select another file</p>");
error = 1;
}else{
data.append('html', file, file.name);
}
}
if(!error){
var xhr = new XMLHttpRequest();
xhr.open('POST', 'upload.php', true);
xhr.send(data);
xhr.onload = function () {
if (xhr.status === 200) {
$("#drop-box").html("<p> File Uploaded. Select more files</p>");
} else {
$("#drop-box").html("<p> Error in upload, try again.</p>");
}
};
}
}
This script work fine with my server side, but i want to be able to perform this html upload every day.Is this possible ? what about SetInterval and SetTimeout ?
You can schedule tasks with JavaScript so that they are executed in specific intervals. But you can not upload files from the local system to the server:
JavaScript can't start file transfers on it's own due to security reasons and always needs manual user interaction to do this.
The reason why your above script works is because fileUpload() is orginally triggered by the user. As soon as you use timeout() or interval(), the browser detects that the operation was not triggered by the user and won't allow you to upload user data.
I am loading external js using $.getScript(url). Now until the js is loaded I want percentage loader (to show how much js is loaded) to be shown. How am I to do this.
$(document).on('click', 'div#play', function(){
$(this).hide();
$('div#stop').css('display', 'block');
$('div#processing_load').show();
var url = 'https://www.gstatic.com/swiffy/v5.4/runtime.js';
$.getScript(url)
.done(function(){
$('div#processing_load').hide();
$('#swiffycontainer').css('display', 'block');
$('.landing-banner').css('display', 'none');
stage = new swiffy.Stage(document.getElementById('swiffycontainer'), swiffyobject);
stage.start();
stage.setBackground(null);
})
})
Here I want to show the loader before done with percentage.Thanks in advance. Any help/suggestion is welcome.
Instead of getScript(), use ajax(), which is more powerful. It also allows you to parse xhr data to set a loading status, I edited your code (untested):
$.ajax({
xhr: function () {
var xhr = new window.XMLHttpRequest();
xhr.addEventListener("progress", function (evt) {
//check if the length of the requested file is computable (if you generate the requested file using php, you require ob_start(); and ob_end_flush();)
if (evt.lengthComputable) {
//Calculate the percentage completed
var percentComplete = Math.floor((evt.loaded / evt.total) * 100) + '%';
//Do something with download progress
$('div#processing_load').show().html(percentComplete);
}
}, false);
return xhr;
},
url: 'https://www.gstatic.com/swiffy/v5.4/runtime.js',
dataType: 'script',
complete: function(xhr) {
//you can use the xhr object to check for response codes
$('div#processing_load').hide();
$('#swiffycontainer').css('display', 'block');
$('.landing-banner').css('display', 'none');
var stage = new swiffy.Stage(document.getElementById('swiffycontainer'), swiffyobject);
stage.start();
stage.setBackground(null);
}
});
I think you can't do it exactly ( show by progress bar)
Why ? Because we don't know that how long time Loading is finished.
But you can use some tips to show progressbar :
You need to know file size and can calculate the internet speed.
time to load = your file size / your internet speed ;
=> show progress bar when you begin to load .
To calculate the speed you can base on
Connection type (2G, 3G, WiFi, wired ) => get its speed
Calculate speed connection at the load time . You can read more in http://stackoverflow.com/questions/4583395/calculate-speed-using-javascript
Using Navigation Timing API: window.performance.*
Finally, Noways to show exactly with progress bar( That depends on networks).
I want to make text area that will handle image drop event on it from the desktop.
I found that I could attach event to html element, but it doesn't work properly. I don't find any error, but it doesn't work.
Here is my code:
var imageDragOver = function imageDragOver(evt)
{
console.log('imageDragOver');
evt.stopPropagation();
evt.preventDefault();
}
var imageDrop = function imageDrop(evt)
{
console.log('imageDrop');
evt.stopPropagation();
evt.preventDefault();
}
document.addEventListener($('textarea'), imageDragOver, false);
document.addEventListener($('textarea'), imageDrop, false);
There is no any message in console log. What I do wrong? I don't look for an already made solutions.
To handle drop event on your area (text area or div) you need to do this:
var dropzone = document.getElementById('ta'); // paste your dropzone id here
dropzone.ondrop = function(e){
console.log('drop'); // for debugging reasons
e.preventDefault(); // stop default behaviour
readfiles(e.dataTransfer.files); // function to handle file(s) that was added to dropzone
};
Next you need to send this files to server and show it in the browser if you want.
function readfiles(files) {
var formData = new FormData(); // we initialise a new form that will be send to php
for (var i = 0; i < files.length; i++) { // if we have more that one file
previewImg(files[i]); // function to preview images
formData.append('file'+i, files[i]);
}
formData.append('moreInfo','myValuableValue');// you can append additional string info
$.ajax({
url: './path_to_file_handler.php',
type: 'POST',
data: formData,
async: true,
success: function (data) {
console.log(data);
},
cache: false,
contentType: false,
processData: false
});
}
function previewImg(file) {
var reader = new FileReader();
reader.onload = function (event) {
var image = new Image();
image.src = event.target.result; // set image source
image.width = 550; // a fake resize
document.getElementById('body').appendChild(image); // append image to body
};
reader.readAsDataURL(file);
}
Code for testing path_to_file_handler.php
<?php
print_r($_POST);
print_r($_FILES);
?>
Hope it will help somebody.
A simple way with jQuery UI, check out:
http://jqueryui.com/draggable/
http://jqueryui.com/droppable/
EDIT:
Duplicate of: Drag and drop desktop to browser HTML5 Javascript ?
Good luck! :-)
I need to check overall progress of the Jquery file upload
I'm allowing my users to upload multiple files, Now I want to know what all the files are completed then I need to trigger a function to do some other work.
I tried all the callbacks but couldn't figure it out.
I even tried this
var activeUploads = $('.new_photographer').fileupload('active');
But its variable is returning some garbage data.
Here's my jquery:
$('.new_photographer').fileupload({
dataType :'json',
fileInput: $(this).find('input:file'),
acceptFileTypes: /(\.|\/)(gif|jpeg|png|jpg)$/i,
dropZone: $(this).find('#dropzone'),
complete : function (e, data) {
var activeUploads = $('.new_photographer').fileupload('active');
var overallProgress = $('.new_photographer').fileupload('progress');
alert(JSON.stringify(activeUploads));
//alert('overallProgress :: '+JSON.stringify(overallProgress));
if ( activeUploads < 0){
window.location.replace("http://stackoverflow.com");
}
}
}).bind('fileuploadsubmit', function (e, data) {
var inputs = data.context.find(':input');
data.formData = inputs.serializeArray();
});
When I use progress event, I can update the progress bar for one uploading request:
function uploadFile(file) {
fileid=md5(file.name);
if {xhr[fileid] ;== undefined} {
xhr[fileid] = new XMLHttpRequest();
xhr[fileid].open('POST',' {% url upload %}', true);
xhr[fileid].setRequestHeader("X-File-Name", file.name);
xhr[fileid].setRequestHeader("X-File-id", fileid);
xhr[fileid].upload.addEventListener('progress', onprogressHandler, false);
xhr[fileid].upload.addEventListener('load',oncompleteHandler,false);
xhr[fileid].send(file);
}
function onprogressHandler(event) {
var percent = event.loaded/event.total*100;
var $target = $(event.target);
console.log(uploadHolder[fileid]);
uploadHolder[fileid].find(".upload-completed").css('width',percent+'%');
console.log('Upload progress: ' + percent + '%');
}
However, when I sent out more than 2 files upload requests at same time, Only the progress bar for the last file will be changed.
How do I determine which file upload request the event is attached to?
Update:
if I declare the fileid as local variable for uploadFile like var fileid, I cannot access fileid in the event handler. Using 'this' in the event handler give me the XMLHttpRequestUpload object.
You should look for "closure" concept for javascript. After that you'll understand the error. And this concept is so important i think, you should learn it :)