📜 ⬆️ ⬇️

Step-by-step instructions on how to implement uploading files to the server without reloading the page in PHP + Javascript

Problem


Recently, I faced a quite common, in my view, common task: you need to ensure that the user can upload any number of, say, pictures with a comment to each of them within the same interface to the server. In my case it was: product photo, its description and quantity. For clarity, I attach a screenshot of the interface:



Idea and solution algorithm


Since descriptions and photos can be changed many times to get the final result, it was decided to implement the following workflow: the photos are uploaded to the server with one click on the photo icon, and if successful, the server returns the name of the picture, and if it fails, “ error ". Accordingly, if successful, the photo icon is replaced with the thumbnail of the loaded photo, and its name is saved in the hidden form field of the corresponding line, and if it fails, we get a photo icon and an empty hidden form field of the corresponding line that is responsible for the photo name. The text information, when changing any form field, is sent to the server all in the array format [namePhoto, descriptionDetails, numberSht] - this is the most universal: the same method is responsible for completely updating the list of products when they are edited or deleted. As you know, AJAX cannot send files, so we will implement the loading procedure using the usual form, as target of which we will specify a hidden frame, which will reload instead of the page.


')

Practical implementation


So, at our disposal HTML, PHP and Javascript. Go:

1. We impose on the page a form for uploading photos. It contains only one input, which we hide using css:

<form enctype="multipart/form-data" action="<?=site_url('otherdetails/uploadOthDetPhoto')?>" method="post" id="othdetphotoform" target="hiddenframe"> <input type="file" id="photoloader" name="photo"/> </form> 

2. Create a hidden iframe on the page, which will reload as a result of sending the form with the file:

 <iframe id="hiddenframe" name="hiddenframe" style="width:0px;height:0px;border:0px"></iframe> 

3. We impose a table of products with which the user will work:

 <table id="othdetails" class="table table-hover borderbottom"> <thead> <tr> <th>№ /</th> <th></th> <th></th> <th></th> <th></th> </tr> </thead> <tbody> <tr> <td class="col-xs-2 col-md-1" style="vertical-align:middle;"></td> <td style="width:110px;"> <img src="photo_icon.png" alt=" " class="img-circle othdet_photo"/> <input class="form-control" type="hidden" name="dform_oth_details_photo[]" value=""/> </td> <td><textarea name="dform_oth_details_descr[]" class="form-control" rows="3" placeholder=" "></textarea></td> <td class="col-xs-2 col-md-1" style="vertical-align:middle;"><input name="dform_oth_details_cnt[]" type="number" class="form-control" value="1" placeholder=""/></td> <td style="vertical-align:middle;text-align:right;"><span class="glyphicon glyphicon-remove removebtn" aria-hidden="true"></span></td> </tr> </tbody> </table> 


In the line of goods we have:


3. Write the PHP file download code:

 public function uploadOthDetPhoto() { $this->isDformSet(); $config['upload_path'] = 'public/uploads/othdet/'; $config['allowed_types'] = 'gif|jpg|png'; $config['max_size'] = '10240'; $config['encrypt_name'] = true; $this->load->library('upload', $config); $this->upload->initialize($config); $this->upload->do_upload('photo'); $arrErrors = $this->upload->display_errors(); if (!empty($arrErrors) > 0){ echo 'error'; }else{ $arrPhotoData = $this->upload->data(); $strFileName = $arrPhotoData['file_name']; echo $strFileName; $intMaxWidth = 800; if ($arrPhotoData['image_width'] > $intMaxWidth){ unset($config); $config['image_library'] = 'gd2'; $config['source_image'] = $arrPhotoData['full_path']; $config['width'] = $intMaxWidth; $config['height'] = $intMaxWidth*$arrPhotoData['image_height']/$arrPhotoData['image_width']; $config['maintain_ratio'] = TRUE; $this->load->library('image_lib', $config); $this->image_lib->resize(); } } } 

My project is on CodeIgniter, so the code is like this, but in general, the essence is as follows: we simply load and rename the file obtained from the form, if everything is successful, we print its name in our iframe, if not - “error”.

4. We write Javascript, which will control the whole process:

 $(function(){ function rownumbers(){ $('#othdetails tbody tr').each(function(i) { var number = i + 1; $(this).find('td:first').text(number); }); } function update(){ var url = '<?=site_url('otherdetails/updateOthDet')?>'; var postData = $('.form-control').serialize(); $.post(url, postData, function(){}, 'json'); } var curimg = ''; var intervalID = ''; function checkphotoname() { var linkedFrame = document.getElementById('hiddenframe'); var content = linkedFrame.contentWindow.document.body.innerHTML; var completed = false; if (content === 'error'){ curimg.attr('src','<?=base_url()?>public/img/photo_icon.png'); $('#error').show(200).delay(6000).hide(200); $('#error').html('<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>    .    - 10 , : jpg,png,gif.'); completed = true; } else if (content !== ''){ curimg.parent().children('.form-control').val(content); curimg.attr('src','<?=base_url()?>public/uploads/othdet/' + content); completed = true; } if (completed === true){ update(); clearInterval(intervalID); $('#hiddenframe').contents().find('body').html(''); } } rownumbers(); $(document).on('click', '.othdet_photo', function(){ $('#hiddenframe').contents().find('body').html(''); curimg = $(this); curimg.attr('src','<?=base_url()?>public/img/photo_icon.png'); curimg.parent().children('.form-control').val(''); update(); $('#photoloader').click(); }); $('#photoloader').change(function(){ curimg.attr('src','<?=base_url()?>public/img/indicator.gif'); $('#othdetphotoform').submit(); $('#photoloader').val(''); }); $('#othdetphotoform').submit(function(){ intervalID = setInterval(checkphotoname, 500); }); $(document).on('change', '.form-control', function(){ update(); }); $("#addnewdet").click(function(){ var emp = 0; $(".form-control[name!='dform_oth_details_photo[]']").each(function(indx){ if ($(this).val() === ''){ emp = 1; $(this).focus(); } }); if (emp === 1){ $('#error').show(200).delay(2000).hide(200); $('#error').html('<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> ,   '); }else{ var row = '<tr><td class="col-xs-2 col-md-1" style="vertical-align:middle;"></td><td style="width:110px;"><img src="<?=base_url()?>public/img/photo_icon.png" alt=" " class="img-circle othdet_photo"/><input class="form-control" type="hidden" name="dform_oth_details_photo[]" value=""/></td><td><textarea name="dform_oth_details_descr[]" class="form-control" rows="3" placeholder=" "></textarea></td><td class="col-xs-2 col-md-1" style="vertical-align:middle;"><input name="dform_oth_details_cnt[]" type="number" class="form-control" value="1" placeholder=""/></td><td style="vertical-align:middle;text-align:right;"><span class="glyphicon glyphicon-remove removebtn" aria-hidden="true"></span></td></tr>'; $("#othdetails tbody").append(row); rownumbers(); $('[name="dform_oth_details_descr[]"]').last().focus(); } }); $(document).on('click', '.removebtn', function(){ $(this).parent().parent().remove(); update(); rownumbers(); }); }); 

Here I will explain in more detail:


That's the whole process.

If the need arises, I will make the demo process a separate block and attach a link here, as well as give the source code.

Thanks for reading!

Source: https://habr.com/ru/post/256197/


All Articles