Multiple file upload in each inputs using CodeIgniter and Ajax - php

I am not able to upload any images after second input. I can only upload the first input. The inputs are created dynamically when another input value is added. Below is the code:
\\ jquery //
function storeupdate(){
$.ajax({
type:"POST",
url:"<?php echo base_url(); ?>updatestore",
data:$("#mainstore").serialize(),
success: function(response){
var data = new FormData();
input = document.getElementById('file');
for(var i = 0; i < input.files.length; i++)
{
data.append('images[]', document.getElementById('file').files[i]);
}
$.ajax({
type: 'POST',
url: '<?php echo base_url(); ?>storeupload',
cache: false,
contentType: false,
processData: false,
data : data,
success: function(result){
console.log(result);
},
error: function(err){
console.log(err);
}
});
swal('Successful!', 'Data has been saved!', 'success');
//window.location.reload();
},
error: function() {
swal("Oops", "We couldn't connect to the server!", "error");
}
});
return false;
};
\\ view //
<input type="file" name="images[]" id="file" class="file" accept="image/*;capture=camera" multiple="multiple" />
<button type="button" class="btn btn-success save" id="save" name="save" onclick="storeupdate();" disabled>Save</button>
\\ controller //
public function storeupload()
{
$files= $_FILES;
$cpt = count ($_FILES['images']['name']);
for($i = 0; $i < $cpt; $i ++) {
$_FILES['images']['name'] = $files['images']['name'][$i];
$_FILES['images']['type'] = $files['images']['type'][$i];
$_FILES['images']['tmp_name'] = $files['images']['tmp_name'][$i];
$_FILES['images']['error'] = $files['images']['error'][$i];
$_FILES['images']['size'] = $files['images']['size'][$i];
$this->upload->initialize ( $this->set_upload_options1() );
$this->upload->do_upload("images");
$fileName = $_FILES['images']['name'];
$images[] = $fileName;
}
}

I made and tested a little sample of code so that you can see what's wrong. You have a few things wrong. First thing I would recommend is actually using jQuery. Your code is obviously using jQuery, but you have all kinds of vanilla JS that can be simplified:
$(document).ready(function(){
$('#save').on('click', function(){
var fileInput = $('#file_input')[0];
if( fileInput.files.length > 0 ){
var formData = new FormData();
$.each(fileInput.files, function(k,file){
formData.append('images[]', file);
});
$.ajax({
method: 'post',
url:"/multi_uploader/process",
data: formData,
dataType: 'json',
contentType: false,
processData: false,
success: function(response){
console.log(response);
}
});
}else{
console.log('No Files Selected');
}
});
});
Notice that I hard coded in the ajax URL. The controller I used for testing was named Multi_uploader.php.
Next is that in your controller when you loop through the $_FILES, you need to convert that over to "userfile". This is very important if you plan to use the CodeIgniter upload class:
public function process()
{
$F = array();
$count_uploaded_files = count( $_FILES['images']['name'] );
$files = $_FILES;
for( $i = 0; $i < $count_uploaded_files; $i++ )
{
$_FILES['userfile'] = [
'name' => $files['images']['name'][$i],
'type' => $files['images']['type'][$i],
'tmp_name' => $files['images']['tmp_name'][$i],
'error' => $files['images']['error'][$i],
'size' => $files['images']['size'][$i]
];
$F[] = $_FILES['userfile'];
// Here is where you do your CodeIgniter upload ...
}
echo json_encode($F);
}
This is the view that I used for testing:
<!doctype html>
<html>
<head>
<title>Multi Uploader</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="/js/multi_uploader.js"></script>
</head>
<body>
<form>
<input type="file" name="images[]" id="file_input" multiple />
<button type="button" id="save">Upload</button>
</form>
</body>
</html>
Finally, just to prove that the files were uploaded to the controller, and that I could use them with CodeIgniter, I send the ajax response as a json encoded array, and display it in the console. See the code comment where you would put your CodeIgniter upload code.
UPDATE (to show what to do with multiple file inputs) ---
If you want to have multiple file inputs, then that obviously changes your HTML and JS a bit. In that case, your HTML would have the multiple inputs:
<input type="file" name="images[]" class="file_input" multiple />
<input type="file" name="images[]" class="file_input" multiple />
<input type="file" name="images[]" class="file_input" multiple />
<input type="file" name="images[]" class="file_input" multiple />
And your javascript needs to change to loop through each input:
$(document).ready(function(){
$('#save').on('click', function(){
var fileInputs = $('.file_input');
var formData = new FormData();
$.each(fileInputs, function(i,fileInput){
if( fileInput.files.length > 0 ){
$.each(fileInput.files, function(k,file){
formData.append('images[]', file);
});
}
});
$.ajax({
method: 'post',
url:"/multi_uploader/process",
data: formData,
dataType: 'json',
contentType: false,
processData: false,
success: function(response){
console.log(response);
}
});
});
});
A little more info about your comment regarding adding the details to your database ---
When you do an upload with CodeIgniter, there is a provided upload summary:
$summary = $this->upload->data();
This is an array of data that ends up looking like this:
$summary = array(
'file_name' => 'mypic.jpg',
'file_type' => 'image/jpeg',
'file_path' => '/path/to/your/upload/',
'full_path' => '/path/to/your/upload/jpg.jpg',
'raw_name' => 'mypic',
'orig_name' => 'mypic.jpg',
'client_name' => 'mypic.jpg',
'file_ext' => '.jpg',
'file_size' => 22.2
'is_image' => 1
'image_width' => 800
'image_height' => 600
'image_type' => 'jpeg',
'image_size_str' => 'width="800" height="200"'
);
So all you would have to do to add a record to your database is this after each upload:
$summary = $this->upload->data();
$this->db->insert('storefiles', array(
'Store_ID' => $_POST['storeid'],
'File_Name' => $summary['file_name'],
'Created' => date('Y-m-d h:i:s'),
'Modified' => date('Y-m-d h:i:s')
));
It's pretty easy to see that you could store a lot more than just the filename.

I know this question is old, but for people like me who encounter this error: is_uploaded_file() expects parameter 1 to be string, array given after using the Code Igniter file upload library within the loop like so:
for ( $i = 0; $i < count($var); $i++ )
{
// other codes here
// Do codeigniter upload
$this->upload->do_upload('images');
}
What you can do is to not put any params in the do_upload() function. Like so:
$this->upload->do_upload();

Related

jQuery - send multidimensional form data to PHP script

I have a jQuery script that adds hidden inputs into a form whenever a certain .class input undergoes a change. Depending on user input, it generates values for other uneditable columns which also get pushed into a form as hidden inputs.
The form output looks like this:
<input type="hidden" name="[1008016BSTL][1][part]" value="1008016BSTL" />
<input type="hidden" name="[1008016BSTL][1][price]" value="123" />
<input type="hidden" name="[1008016BSTL][1][priceExVat]" value="102.50" />
<input type="hidden" name="[1008016BSTL][1][fee]" value="10.53" />
<input type="hidden" name="[1008016BSTL][1][profit]" value="68.41" />
This is just one set of data I'm trying to capture, but it's the same for the others, save the original key and sub-key.
My form wrapper looks like this:
<form method="post" id="submit-form" enctype="multipart/form-data">
<input type="submit" value="Save" />
</form>
With my AJAX looking like:
$('form#submit-form').submit(function(e)
{
e.preventDefault();
let data = $('form#submit-form').serializeArray();
$.ajax({
url: '/save-pricing.php',
data: {data: JSON.stringify(data)},
type: 'post',
success: function(res)
{
console.log(res)
},
error: function(res)
{
alert('Error! I won\'t tell you what it is. But, I\'ll give you a clue: 21');
console.log(res)
}
})
})
I've also tried (for setting data):
let data = $('form#submit-form').serialize();
data = JSON.stringify(data);
$.ajax({
...
data: {data: data}
...
})
As well as omitting the .stringify() function.
This comes through to PHP like this:
<?php
echo '<pre>'. print_r($_POST, 1) .'</pre>';
/**
* Below is for .serialize() -> output is an empty array
*
* parse_str($_POST['data'], $postData)
* echo '<pre>'. print_r($postData, 1) .'</pre>';
*/
simplified output (just removing the other sets) with .serializeArray():
Array
(
[data] => [
{"name":"[1008016BSTL][1][part]","value":"1008016BSTL"},
{"name":"[1008016BSTL][1][price]","value":"123"},
{"name":"[1008016BSTL][1][priceExVat]","value":"102.50"},
{"name":"[1008016BSTL][1][fee]","value":"10.53"},
{"name":"[1008016BSTL][1][profit]","value":"68.41"}
]
)
This is OK I guess, I could probably group by name and merge into an array, but there feels like it should already do this with .serialize() on jQuery-side and then parse_str() on the PHP side.
However, as I've mentioned, parse_str() and .serialize() yield an empty array, which I can't use.
so my question is: How do I successfully send multi-dimensional form data to PHP via jQuery?
Edit
Added:
dataType: 'json'
with .serialize() and then JSON.stringify(data), removed parse_str() and it outputs:
Array
(
[\"] => Array
(
[1008016BSTL] => Array
(
[1] => Array
(
[part] => 1008016BSTL
)
)
)
)
Input fields names with brackets are not treated nicely by serializeArray. This below code will create a proper multidimentional array you can send back to the server.
$('form#submit-form').submit(function(event)
{
event.preventDefault();
//Prevent the form from submitting
var fields = {};
//This is where you're gonna store your form fields
$.each($('form#submit-form').serializeArray(), function(i, field) {
//Get values, even from multiple-selects
if (Array.isArray(fields[field.name])) {
fields[field.name].push(field.value);
} else if (typeof fields[field.name] !== 'undefined') {
var val = fields[field.name];
fields[field.name] = new Array();
fields[field.name].push(val);
fields[field.name].push(field.value);
} else {
fields[field.name] = field.value;
}
});
//Now all the fields are in the fields object
//You're now going to translate "key[subkey]" string to key[subkey] object
for (var key in fields) {
var parts = key.split(/[[\]]{1,2}/);
parts.length--;
if (parts.length) {
var val = fields[key];
delete fields[key];
addToTree(fields, parts);
setToValue(fields, val, parts);
}
//input field array names (with brackets) are mistakenly treated as strings, this fixes it
}
$.ajax({
url: '/save-pricing.php',
data: JSON.stringify(fields),
contentType: 'application/json',
type: 'post',
success: function(res) {
console.log(res)
},
error: function(res) {
alert('Error! I won\'t tell you what it is. But, I\'ll give you a clue: 21');
console.log(res)
}
})
});
/**
* Adds values to a tree.
* #link https://stackoverflow.com/questions/3663096/how-to-convert-array-to-tree
*/
function addToTree(tree, array) {
for (var i = 0, length = array.length; i < length; i++) {
tree = tree[array[i]] = tree[array[i]] || {}
}
}
/**
* Sets object values.
* #link https://stackoverflow.com/questions/13719593/how-to-set-object-property-of-object-property-of-given-its-string-name-in-ja
*/
function setToValue(obj, value, path) {
for (i = 0; i < path.length - 1; i++) {
obj = obj[path[i]];
}
obj[path[i]] = value;
}
with the PHP side using json_decode:
$data = json_decode(file_get_contents('php://input'), true);
echo '<pre>'. print_r($data, 1) .'</pre>';
For your particular issue you can the jquery.serializeJSON
Here is the link of their github https://github.com/marioizquierdo/jquery.serializeJSON
This will create the correct json object.
This is simplest solution I have for this case.
<?php if(isset($_POST["data"])) {
$post_data = urldecode($_POST["data"]);
parse_str($post_data, $form_data);
// this will give you first element of array by eliminating double quote key ('') in post data array, which is also desired
$form_data = reset($form_data);
echo '<pre>'; print_r($form_data); echo '</pre>'; exit;
} else { ?>
<form method="post" id="submit-form">
<input type="hidden" name="[1008016BSTL][1][part]" value="1008016BSTL" />
<input type="hidden" name="[1008016BSTL][1][price]" value="123" />
<input type="hidden" name="[1008016BSTL][1][priceExVat]" value="102.50" />
<input type="hidden" name="[1008016BSTL][1][fee]" value="10.53" />
<input type="hidden" name="[1008016BSTL][1][profit]" value="68.41" />
<input type="submit" value="Save" />
</form>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$("#submit-form").on('submit', function(e){
e.preventDefault();
var form_data = $("#submit-form").serialize();
$.ajax({
type: "POST",
data: {data: JSON.stringify(form_data)},
success: function(res){
console.log(res);
}
});
});
</script>
<?php } ?>

Upload PDF on CodeIgniter 3.1.9

It tells me The filetype you are attempting to upload is not allowed.
$config['upload_path'] = './' . URL_FILES_ALUMNOS;
$config['allowed_types'] = 'gif|jpg|png|jpeg|pdf';
$config['file_name'] = uniqid();
$this->load->library('upload', $config);
$this->upload->initialize($config);
I've readed in SO that it may be missing this:
'pdf' => array('application/pdf', 'application/force-download', 'application/x-download', 'binary/octet-stream')
But is not missing.
I don't know if another portion of code is needed to figure out what's happening
Thanks
You should try this code. i hope it will work for you
form data is
<div class="form-group">
<label for="pdf1">File input</label>
<input type="file" id="pdf1" name="pdf1">
</div>
AJAX CODE
$(document).on('submit','#form_id',function(event){
event.preventDefault();
var pdf1= $('#pdf1').val().split('.').pop().toLowerCase();
if(jQuery.inArray(pdf1, ['gif', 'png', 'jpg', 'jpeg','pdf']) == -1)
{
alert("invalid File extention");
$('#pdf1') . val('');
return false;
}
$.ajax({
url: "<?php echo base_url();?>Home/upload_pdf",
method: 'POST',
data: new FormData(this),
contentType: false,
processData: false,
success: function(data)
{
}
});
});
CONTROLLER FUNCTION
function upload_pdf(){
$id = $this->input->post('img_id');
$content = array(
'text1' => $this->input->post('text1'),
'text2' => $this->input->post('text2'),
'img2' => $this->upload_pdf_function()
);
// insert this array here;
}
public function upload_pdf_function()
{
if(isset($_FILES['img2']))
{
$pdf1= explode('.', $_FILES['pdf1']['name']);
$new_name = rand().'.'.$pdf1[1];
//$destination = '/vendor_images'.$new_name;
move_uploaded_file($_FILES['pdf1']['tmp_name'], 'directory_name/folder_name/'.$new_name);
return $new_name;
}
}

Jquery file upload not working in Laravel

I have tried majority of other questions here and other solutions and nothing has worked so far.
What I am trying to accomplish is upload images before Laravel's validation takes place, obviously I can't use the create function because it wont be hit until validation succeeds so I have made a custom function to do the file saving server side and trying to use Ajax to call that function every time a file is selected.
Current issue: doesn't seem like my Ajax is running on debugging its being skipped over,
second issue: I have a csrf token in my master template do i still need to add the ajax setup? if so is the way i am doing it correct.
Route:
Route::post('/upload', 'UploadController#uploadSubmit');
View:
<div>
<input type="file" id="fileupload" name="photos[]" data-url="/upload" multiple />
<br />
<div id="files_list"></div>
<p id="loading"></p>
<input type="hidden" name="file_ids" id="file_ids" value="" />
</div>
Ajax call:
$(document).ready(function(){
$("input").change(function(){
alert('triggered');
debugger;
$('#fileupload').fileupload({
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $(meta[name="csrf-token"]).attr('content')
}
dataType: 'json',
add: function (e, data) {
$('#loading').text('Uploading...');
data.submit();
},
done: function (e, data) {
$.each(data.result.files, function (index, file) {
$('<p/>').html(file.name + ' (' + file.size + ' KB)').appendTo($('#files_list'));
if ($('#file_ids').val() != '') {
$('#file_ids').val($('#file_ids').val() + ',');
}
$('#file_ids').val($('#file_ids').val() + file.fileID);
});
$('#loading').text('');
}
});
});
});
});
Controller:
public function uploadSubmit(Request $request){
$files = [];
dd(request());
foreach($learnerFiles as $key => $learnerFile){
if(count($learnerFile) > 0){
$path = $learnerFile->storeAs('public/uploads/learners', request('idNumber').'_'.$key.'.'.$learnerFile->extension());
$search = 'public/' ;
$trimmed = str_replace($search, '', $path) ;
//dd($learnerFiles);
$file = FileUpload::create([
'user_id' => $learner->id,
'file_name' => $key,
'path' => $trimmed
]);
}
else{
}
$file_object = new \stdClass();
$file_object->name = $key;
$file_object->size = round(Storage::size($path) / 1024, 2);
$file_object->fileID = $learner->id;
$files[] = $file_object;
}
return response()->json(array('files' => $photos), 200);
}
I'm using the following method to upload images using Ajax call and Laravel back-end.
var uploader = $('#image-uploader[type="file"]');
var data = new FormData();
$.each(uploader.files, function() {
data.append('image[]', this);
});
data.append('_token', $('[name="csrf-token"]').attr('content'));
var url = '/upload'; //Or any target path with post method
$.ajax({
url: url,
method: 'POST',
data: data,
processData: false,
contentType: false,
success: function(data) {
alert('succeed');
}
});
Consider you can access to image files in server-side using $_POST['image] array.
Hope this helps you.

Trying to save the image to the database as well as show it in view in codeigniter using ajax only works after page loads

Created a normal upload image system and uploaded the image to the database now when i click on upload the image does not show itself on the div assisgned but i have to reload the page again to see that uploaded image what can i use to show the image with ajax submit
here is the code
<div id="timelineProfilePic"><?php
{
$image_properties = array('src'=> base_url("uploads/" . $image_file),'width' => '200px','height'=> '200px','id'=>'profilepic','rel' => 'lightbox');
echo img($image_properties);
?>
<div id="profilepicselector">
<?php echo form_open_multipart('',["id"=>"form_profile"]); ?>
<input type="hidden" name="id" value="<?php echo $id ;?>" >
<?php echo form_upload(["name"=>"imagefile"]); ?>
<?php echo form_submit(["name"=>"submit","value"=>"Submit"]); ?>
<?php echo form_close(); ?>
</div>
<?php
}
?></div>
jQuery('#form_profile').submit(function(e){
e.preventDefault();
var formData = new FormData(this);
var url= '<?php echo base_url("user/do_upload"); ?>';
formData.value
jQuery.ajax({
type: "POST",
url:url,
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(data)
{
$('#profilepic').attr('src',data);
},
error: function(data){
//error function
}
});
});
public function do_upload()
{
$config = [
'upload_path' => './uploads',
'allowed_types' => 'jpg|gif|png|jpeg',
'max_size' => 1100000000,
'max_width' => 102400000,
'max_height' => 76800000,
];
$this->load->library('upload', $config);
$this->upload->initialize($config);
if($this->upload->do_upload('imagefile'))
{
$post = $this->input->post();
unset($post['submit']);
//print_r($post);
$upload_data = $this->upload->data();
print_r($upload_data);
$file_name=$_FILES['imagefile'];
$this->load->model('Pmodel');
$this->Pmodel->upload_model($post,$file_name);
$image_path_profile= base_url("uploads/".$upload_data['raw_name'].$upload_data['file_ext']);
}
else
{
$upload_error = $this->upload->display_errors();
$this->load->view('dashboard/profile',compact('upload_error'));
}
}
found the error it was a silly mistake. i needed to echo the image path so that it will change when i click on ajax submit at the end like this
echo $image_path_profile= base_url("uploads/".$upload_data['raw_name'].$upload_data['file_ext']);
this will return the image at the same time i am uploading it.
thanx for your reply

fckediter removing formatting in codeigniter

I am using FCKEditer with codeigniter and when I submit data to database, it remove formatting before submitting data.
for example, if I submit
<span style="color: rgb(255, 0, 0);">know-how in the field of Water</span>
the data store in table will be
<span>know-how in the field of Water</span>
I have form like below
<form action="#" method="post" id="frm" name="frm" class="form_class">
<label id="validateeditor" >Description</label>
<?
$dataf = array(
'name' => 'page_description',
'id' => 'page_description',
'toolbarset' => 'Default',
'basepath' => base_url().'application/plugins/fckeditor/',
'width' => '700',
'height' => '400'
);
echo form_fckeditor( $dataf, #$result['page_description']);
</form>
I am using following jquery code to save data in database
<script type="text/javascript">
$(document).ready(function(){
jQuery("#frm").validationEngine('attach',{
promptPosition :'centerRight',
onValidationComplete: function(form, status){
if(status)
{
insert_update();
}
}
})
});
function insert_update()
{
var fckvalue = FCKeditorAPI.GetInstance('page_description').GetXHTML();
$("#page_description").val(fckvalue);
var formdata = $("#frm").serialize();
$.ajax({
type: 'POST',
url: '<?php echo site_url(ADMIN_DIR."cms/insert_update"); ?>',
data: formdata,
success:function (data){
var msg;
if(jQuery.trim($("#<?php echo $u_column;?>").val())!='')
{
msg = "Record Updated Successfully.";
}
else
{
msg = "Record Inserted Successfully.";
}
jQuery.noticeAdd({text:msg});
$("#list").trigger("reloadGrid");
editDialog.dialog("close");
}
});
}
</script>
I don't know what is wrong but when I save data it remove formatting as above.
This is happening as a result of XSS filtering on your input.
Here are a few things you should check to ensure this field doesn't get cleaned:
You might have a validation rule filtering the input: $this->form_validation->set_rules('page_description', 'Description', 'required|xss_clean');
Check if $config['global_xss_filtering'] = TRUE; in your config.php file.
Your input will be filtered if you pass TRUE as a second parameter on the input: $this->input->post('page_description', TRUE);

Categories