What changes, please, can I make to the code below, so that my upload.php file can receive multiple files which I would them loop through to process? I have been trying to upload multiple files at once to server using Summernote. Although, I select multiple files from my laptop for the upload, only one file gets uploaded. I feel certain that the PHP file which handles the upload is not the problem because it receives only one file even if I select multiple files for upload. Below is how the JQuery code looks like
$('.summernote-mini').summernote({
height: 200,
tabsize: 2,
callbacks: {
onFileUpload: function(files) {
callBack(files[0]);
},
}
});
Callback Function
function callBack(files) {
let data = new FormData();
data.append('media_upload[]', files);
$.ajax({
data: data,
type: "POST",
url: "upload.php",
cache: false,
contentType: false,
processData: false,
xhr: function() { //Handle progress upload
let myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
return myXhr;
}
}).done(function(reponse){
//I handle the response here
});
}
Regardless of the number of files I select to upload, count($_FILES['media_upload']['name']) gives me 1 in my e.g upload.php file which handles the server side file upload. What could be the solution to this problem?
After receiving assistance from #Fravadona I got the solution to the problem.
I replaced callBack(files[0]); with callBack(files);as #Fravadona suggested.
Then, in the call back function, I replaced data.append('media_upload[]', files); with the code below:
var iLength = files.length;
var i;
for(i = 0; i < iLength; i++){
data.append("media_upload[]", files[i]);
}
So the correct code has become this:
$('.summernote-mini').summernote({
height: 200,
tabsize: 2,
callbacks: {
onFileUpload: function(files) {
callBack(files);
},
}
});
And the call back function has become this:
function callBack(files) {
let data = new FormData();
var iLength = files.length;
var i;
for(i = 0; i < iLength; i++){
data.append("media_upload[]", files[i]);
}
$.ajax({
data: data,
type: "POST",
url: "upload.php",
cache: false,
contentType: false,
processData: false,
xhr: function() { //Handle progress upload
let myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
return myXhr;
}
}).done(function(reponse){
//I handle the response here
});
}
So now, I am able to successfully upload multiple files at once using Summmernote.
Related
I've recently used lots of Ajax methods in one of my projects, since in every $.ajax call you have to write many of the same codes, like:
{
type:'POST', // Default value is 'GET'
beforeSend: function(xhr){
// Usually do some Page Loading Animation stuff here
},
error:function(){
// Handling the Exceptions here
}
}
So I've encapsulated the Ajax call into a class, called JAjax, like this :
(function ($) {
// More details, see: http://api.jquery.com/jquery.ajax/
var defaults = {
data: {},
url: '',
type: 'POST',
dataType: 'JSON',
isOverlay: true,
async: true,
cache: true,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
processData: true,
overlayTarget: $(document.body),
dealyClean: 500,
f_before: function () {},
f_done: function () { },
f_always: function () { },
f_fail: function (xhr) {
if (xhr.status !== 200) {
// Handling the Exceptions
}
}
};
function JAjax(_options) {
this.options = $.extend({}, defaults, _options);
this.execute();
}
function createOverLayer(options) {
// Create a page loading animation layer
}
JAjax.prototype = {
execute: function () {
var parent = this;
var response = $.ajax({
data: parent.options.data,
url: parent.options.url,
type: parent.options.type,
dataType: parent.options.dataType,
contentType: parent.options.contentType,
async: parent.options.async,
cache: parent.options.cache,
processData: parent.options.processData,
beforeSend: function (xhr) {
parent.options.f_before();
if (parent.options.isOverlay) {
createOverLayer(parent.options);
}
}
});
response.done(parent.options.f_done);
response.always(parent.options.f_always);
response.fail(parent.options.f_fail);
}
};
jQuery.extend({
jajax: function (_options) {
_options = _options || {};
if (typeof _options === 'object') {
return new JAjax(_options);
}
}
});
})(jQuery);
For most Ajax requests (GET, POST), it works fine. But when I use it to upload some files, The file will successfully upload to the server and back to me a filename(string) as an execution result. But somehow, it doesn't trigger the f_done function, below is how I use it to upload the files:
var url = '/ajax_common_file_upload';
var file_data = new FormData();
for (var i = 0; i < _files.length; i++) {
var file = _files[i];
file_data.append('input_files[]', file);
}
$.jajax({
url: url,
data: file_data,
cache: false,
contentType: false,
processData: false,
f_done: function (result) {
// Never to be executed :-(
alert('show me something, please!');
}
});
I spend days to try to figure it out why it doesn't 'SHOW ME SOMETHING' but all failed, will be very appreciated that someone can help me out and explain why the f_done() method cannot be triggered when I use it to upload files.
Update:
I made some screenshots for both JAjax and original $.ajax on Request Headers and merge them together like below:
I used the same parameters to make the request for both JAjax and $.ajax, but I don't know why they have a different Accept value!
ANYONE?
Still can not trigger the f_done() function!!! but since I can do the same thing at f_always(), I'm gonna skip this and moving on. I will keep this post open and always appreciate for any suggestions!
I'm trying to upload multiple files from a drag/drop event using jQuery/AJAX/Laravel.
MY DROP EVENT:
$( document ).on('drop dragleave', '.file-drag', function(e){
$(this).removeClass('drop-ready');
if(e.originalEvent.dataTransfer.files.length) {
e.preventDefault();
e.stopPropagation();
if (e.type === "drop") {
var files = e.originalEvent.dataTransfer.files;
AjaxFileUpload(files)
}
}
});
MY UPLOAD SCRIPT:
function AjaxFileUpload(files){
console.log(files);
//Start appending the files to the FormData object.
var formData = new FormData;
formData.append('_token', CSRF_TOKEN);
for(var i = 0; i < files.length; i++){
formData.append(files[i].name, files[i])
}
console.log(formData.entries());
$.ajax({
//Server script/controller to process the upload
url: 'upload',
type: 'POST',
// Form data
data: formData,
// Tell jQuery not to process data or worry about content-type
// You *must* include these options!
cache: false,
contentType: false,
processData: false,
// Error logging
error: function(jqXHR, textStatus, errorThrown){
console.log(JSON.stringify(jqXHR));
console.log('AJAX Error: ' + textStatus + ": " + errorThrown);
},
// Custom XMLHttpRequest
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
// For handling the progress of the upload
myXhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
$('progress').attr({
value: e.loaded,
max: e.total,
});
}
} , false);
}
return myXhr;
},
success: function(data){
console.log(data);
}
});
}
MY CONTROLLER CODE:
class UploadsController extends Controller
{
public function UploadFiles(Request $request){
return $request->all();
}
}
I THINK my images are getting to the server side, as when I return the request object, I get the following in console:
Thus, the CSRF token is getting through, and the images (I think?) are getting through. My problem from here is accessing the files with PHP and storing them via ->store();.
In the countless examples online/documentation, they typically use something along the lines of:
$path = $request->photo->store('images');
However, I don't understand the 'photo' aspect of this. What if a video or a PDF is uploaded? I basically don't understand how I am to access the different parts of the request object. Documentation on Laravel site is pretty sparse for this and only gives an example using 'photo' of which it never explains.
Figured it out.
In my uploadscontroller:
class UploadsController extends Controller
{
public function UploadFiles(Request $request){
$arr = [];
foreach($request->all() as $file){
if(is_file($file)){
$string = str_random(16);
$ext = $file->guessExtension();
$file_name = $string . '.' . $ext;
$filepath = 'uploads/' . Auth::user()->username . '/' . $file_name;
$file->storeAs(('uploads/' . Auth::user()->username), $file_name);
array_push($arr, [$file_name, $filepath]);
}
}
return $arr;
}
}
This took me a while but I finally got a working solution. I'm using Dropzone so the list of file objects is returned by getAcceptedFiles() but it should be the same concept for you. I'm also attaching the files to an existing form.
Upload:
var formElement = document.getElementById("addForm");
var formData = new FormData(formElement);
// Attach uploaded files to form submission
var files = myDZ.getAcceptedFiles(); // using Dropzone
for (var i = files.length - 1; i >= 0; i--) {
formData.append('files[]', files[i]);
}
$.ajax({
url: 'home/',
data: formData,
processData: false,
contentType: false,
timeout: 1000,
type: 'POST',
headers: {
'X-CSRF-TOKEN': Laravel.csrfToken,
},
success: function(){
...
},
error: function (jqXHR, textStatus) {
...
}
});
Controller:
foreach($request->only('files') as $files){
foreach ($files as $file) {
if(is_file($file)) { // not sure this is needed
$fname = $file->getClientOriginalName();
$fpath = $file->store('docs'); // path to file
}
}
}
Dropzone Script:
Dropzone.autoDiscover = false;
var myDZ = new Dropzone("#my-dropzone", {
url: "/home/files",
maxFilesize: 5,
maxFiles: 5,
addRemoveLinks: true,
dictDefaultMessage: 'Drop files here or click to upload <br> (max: 5 files)',
headers: {
'X-CSRF-TOKEN': Laravel.csrfToken
},
});
Regarding the examples found in Laravel's documentation, 'photo' is simply making use of a magic method to reference a file uploaded with a name of 'photo'. You can replace 'photo' with whatever your specific file names is/are. Specific functions capable of being called on your uploaded files can be found here.
I have a browse button by which user can browse file upto 100 mb. But the problem is, it is uploading the attch file when user submitting the form. And it is not showing in anywhere that how much file uploaded. I want to show it with a progressbar.
U can visit my site http://historikindia.com/contact_us.php.
Please help me to do it. It is now sending attachment to my email. but i need to show user the progressbar otherwise they may think that it is not responding properly (for large file upload).
Here is the code from ajax uploader which updated a status bar. You need to have an html5 progress bar in your html page for it to work.
function progressHandlingFunction(e){
if(e.lengthComputable){
$('progress').attr({value:e.loaded,max:e.total});
}
}
$('#btnupload').click(function(){
var formData = new FormData(document.getElementById('fileupload'));
$.ajax({
url: 'upload.php', //server script to process data
type: 'POST',
xhr: function() { // custom xhr
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // check if upload property exists
myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
}
return myXhr;
},
//Ajax events
beforeSend: function (e) { return true; },
success: function (json) { return true; },
error: function (json) { return false; },
// Form data
data: formData,
dataType: "json",
//Options to tell JQuery not to process data or worry about content-type
cache: false,
processData: false
});
});
html5 progress bar looks like this
<progress value="1" max="100"></progress>
I am trying to create a simple jquery file upload following the steps in this tutorial: http://net.tutsplus.com/tutorials/javascript-ajax/uploading-files-with-ajax/ and it is fully functional and excellent. However I want to have more control and more security over what users can upload images, for example I want to be able to send a token as well. Here is my original code:
$('#images').change(function (evt) {
$('#response').text("Uploading . . .");
var amount = this.files.length;
var reader, file;
alert(formdata);
for (var i = 0; i < amount; i++ ) {
file = this.files[i];
if (!!file.type.match(/image.*/)) {
if ( window.FileReader ) {
reader = new FileReader();
reader.onloadend = function (e) {
appendUploadedPic(e.target.result, file.fileName);
};
reader.readAsDataURL(file);
}
if (formdata) {
formdata.append("images[]", file);
}
}
}
if (formdata) {
$.ajax({
url: "php/upload.php",
type: "POST",
data: formdata,
dataType:'json',
processData: false,
contentType: false,
success: function (res) {
$('#response').html(res['image_name']);
}
});
}
});
and the php is simple so far
foreach ($_FILES["images"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$name = $_FILES["images"]["name"][$key];
move_uploaded_file( $_FILES["images"]["tmp_name"][$key], "../members/" . $_FILES['images']['name'][$key]);
}
}
$respond = array("filename" => $_FILES["images"]["name"][0], "type" => "image");
echo json_encode($respond);
now what I want to do is this
$.ajax({
url: "php/upload.php",
type: "POST",
data: 'token=someToken&code=upload&data='+formdata,
dataType:'json',
processData: false,
contentType: false,
success: function (res) {
$('#response').html(res);
}
});
Is it possible? If so, how would I read it from php? It its a post method i normally use a $_POST['code'] and $_POST'token'], but how would I read the images formdata object?
If formdata was created with FormData, you append additional fields like this:
formdata.append(name, value);
So, if you want to add a token field and a code field, it's:
if (formdata) {
formdata.append("images[]", file);
formdata.append("token", "someToken");
formdata.append("code", "someCode");
}
However, you should be aware that this method of uploading won't be supported by a lot of browsers, namely IE6-IE9, which represents about half of all internet users, I believe.
I recommend using a plugin that detects browser support and uses the best available method. I wrote this plugin for exactly that purpose:
https://github.com/LPology/Simple-Ajax-Uploader
There's a link to a demo at the top to try it out. If you decide to use it and run into any issues, just ping me and I can help you out. Good luck.
I am trying to upload a file using jQuery's $.ajax function but didn't get any output.
Somebody please help me to solve this.
I don't know if this script is correct.
My script is:
$.ajax({
url:'newsup.php',
data: "",
type: 'POST',
contentType:'multipart/form-data',
dataType: 'json',
catche: 'false',
success:function(data6)
{
$("#disp").removeClass().addClass((data6.error=== false)? 'success':'error').html(data6.msg).fadeIn('fast');
//dele();
if($("#disp").hasClass('success'))
{
alert("success");
setTimeout("$('#disp').fadeOut('slow')",3000);
}
},
error:function(XMLHttpRequest,textStatus,errorThrown)
{
$("#disp").removeClass().addClass('error').html("There was an <strong>"+errorThrown+"</strong> error due to <strong>"+textStatus+" condition").fadeIn('fast');
}
});
Also I need help getting data from file uploading field using jQuery.
Please use plugin for this.In my opinion this plugin is better solution for this.You don't need to remember all options etc.Just replace your 'ajax' to 'ajaxForm'.
Please read examples ,below
http://jquery.malsup.com/form/#ajaxForm
This is how I've done it. Use the FormData object.
Note: The odd syntax of the for statement is just setting "f" to the array[i] instance.
$("#submit").click(function () {
var formData = new FormData();
for (var i = 0, f; f = fileArray[i]; i++) {
formData.append("opmlFile", f);
}
$.ajax({
url: "/Documents/SaveFiles/" + #Model,
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false
})
.error(function (xhr, status, error) {
$.notify(error, true);
})
.success(function (data, status, xhr) {
$.notify("Success");
});
});
Unfortunately I don't recall which article I got this from, but it was someone else on Stack Overflow.
AJAX doesnt support file uploading. There are plugins like ajaxfileupload which basically creates a hidden form and uploads your file dynamically.
take a look here and read Oli's answer
I'm using this and it's working fine:
$('#btnUploadFile').on('click', function () {
var data = new FormData();
var files = $("#fileUpload").get(0).files;
// Add the uploaded file content to the form data collection
if (files.length > 0) {
data.append("upload", files[0]);
}
// Make Ajax request with the contentType = false, and procesDate = false
var ajaxRequest = $.ajax({
type: "POST",
url: "/api/documents",
contentType: false,
processData: false,
data: data,
error: function (xhr, status, error) {
console.log(xhr);
console.log(status);
console.log(error);
console.log(data);
}
});
ajaxRequest.done(function (xhr, textStatus) {
$("#response").attr('class', "alert alert-success");
$("#response").html("File uploaded successfully");
});
});
You can use either of the two plugins Jquery File Upload Plugins 1 or Jquery File Upload Plugins 2 and there's no errors on this script.
Hope it helps
Thanks,
Rashid
Ajax supports File upload using FormData Object, Also supports in all major browser except IE8/9
See below
https://developer.mozilla.org/en-US/docs/Web/API/FormData
Another option would be to base64 encode the file contents and send it as a string, decoding it at the back-end.
Simply use submit event on form to send the files and prevent default form action
$('#form').submit(function(e) { return false; });
and get the file on the server side via
$_FILES['inputName'];