I want to upload image in my codeigniter 3 , and I want to show the uploaded image to my users (this is in register level and users is inputing his profile data)
I should showe the uploaded image to him.
I have read this :
Moving it outside of the public_html is a good idea, also try to
rename the file and just add the extension to it.
and another :
Do not move uploaded file to directory which is accessible from URL
but I don't know how can I have show the picture which is not directory which is accessible from URL ! .
I don't have any idea it's really important for me the security I have used codeigniter upload class and I don't you know what kind of security other operations should I do
this is my controller :
public function do_resize($img_name ,$image_original_width , $image_original_height )
{
// $nesbat = $image_original_height / $image_original_width ;
$config_manip = array(
'image_library' => 'gd2',
'source_image' => '../uploads/'.$img_name,
'new_image' => '../uploads/'.$img_name,
'maintain_ratio' => TRUE,
'create_thumb' => TRUE,
'thumb_marker' => '_thumb',
'width' => 150,
'height' => 150
);
$this->load->library('image_lib', $config_manip);
if (!$this->image_lib->resize()) {
// echo $this->image_lib->display_errors();
return false ;
}
else
{
return true ;
}
// clear //
$this->image_lib->clear();
}
function do_upload()
{
$file_name = $this->input->post("file_name") ;
$config['upload_path'] = '../uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '10000';
$config['max_width'] = '1024';
$config['max_height'] = '768';
$config['file_name'] = $file_name;
// delete if .gif image exists before
if ( is_file('./uploads/'.$file_name.".gif") )
{
unlink("./uploads/".$file_name.".gif");
unlink("./uploads/".$file_name."_thumb.gif");
}
// delete if .gif image exists before
if ( is_file('./uploads/'.$file_name.".jpg") )
{
unlink("./uploads/".$file_name.".jpg");
unlink("./uploads/".$file_name."_thumb.jpg");
}
// delete if .gif image exists before
if ( is_file('./uploads/'.$file_name.".png") )
{
unlink("./uploads/".$file_name.".png");
unlink("./uploads/".$file_name."_thumb.png");
}
$this->load->library('upload', $config);
if ( ! $this->upload->do_upload())
{
$error = array('error' => $this->upload->display_errors());
echo "<div id='upload_status'>fail</div>";
echo "<div id='error_mesage'>".$this->upload->display_errors()."</div>";
}
else
{
$data = array('upload_data' => $this->upload->data());
$upload_data = $this->upload->data();
$uploaded_file_name = $upload_data['file_name'];
$resize = $this->do_resize($uploaded_file_name , $upload_data['image_width'] , $upload_data['image_height'] ) ;
if ($resize == true )
{
echo "<div id='upload_status'>success</div>";
echo "<div id='uploaded_image_link' >".$upload_data['file_name']."</div> ";
$thumb_link = str_replace($file_name,$file_name."_thumb",$upload_data['file_name']);
echo "<div id='uploaded_image_thumb_link' >".$thumb_link."</div> ";
}
//if $resize == true , nabashe -> uploade koli fail eleam mishe ta dobare anjam beshe
else
{
echo "<div id='upload_status'>fail</div>";
}
}
}
Images are generally a public asset but you can protect them in a few ways.
Put an index.html or index.php file in your images directory.
Turn off directory listing in your .htaccess file
Rewrite the file name (will obfuscate orginal name)
To view the image after it's uploaded will require AJAX, or a page refresh. A page refresh is easier to code, simply upload the file and show that file on the preceeding page.
You can protect the folder to make sure a particular page has access to displaying an image. This makes things more complicated but working with some kind of resource access system might help you achieve this.
Once the page is loaded though - the image will be available to that user and once downloaded there.
I am not sure on what youre protecting exactly (profile pics, adult content..) but images, like CSS files are public assets.
Rich
Using this way, we can prevent Image call from other server.
Prevent image hotlinking (IMP)
- Image hotlinking is the process/technique of using someone else’s Image URL in our Website and using their bandwidth. In order to prevent this mystery, we can prevent access for external server by adding following line in htaccess.
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourdomain.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]
Just create a blank index.html file and put the index.html file on all other public folders except application/system folders (they already have it).
This is a simple security technique to restrict viewers to view your files on public folders.
Related
I am trying to upload images via CKEditor 5, the image is uploaded fine but CKEditor shows this error: "cannot upload file" and removes the image from the editor
cannot upload file
This is my controller:
public function uploadCkeditor()
{
$config['upload_path'] = './assets/admin/img/uploads';
$config['allowed_types'] = 'gif|jpg|png|jpg';
$config['max_size'] = 2000;
$new_name = 'blog-'.date("Y-m-d").'-'.time();
$config['file_name'] = $new_name;
$this->load->library('upload', $config);
if(!$this->upload->do_upload('upload')){
echo json_encode(array('error'=> $this->upload->display_errors()));
} else {
$uploadData = $this->upload->data();
echo json_encode(array('file_name'=> $uploadData['file_name']));
}
}
This is CKEditor script:
<script src="<?= base_url();?>assets/admin/js/ckeditor.js"></script>
<script>
var myEditor;
ClassicEditor.create(document.getElementById('detail'),
{
ckfinder: {
uploadUrl: 'uploadCkeditor'
}}).then( editor => {
console.log( 'Editor was initialized', editor );
myEditor = editor;} ).catch( err => {
console.log( err );} );</script>
I ran into the same issue, and fixed it by returning the following json response at the end of my upload handling function:
return new JsonResponse([
'uploaded' => true,
'fileName' => $image,
'url' => $url
], 200);
It seems like you can also include an error, with a number and a message key, if needed.
Note that I ran into this issue in a Symfony project, rather than a Codeigniter project, but It should work the same way. My answer is based on this answer.
My code is running fine and adding the files correctly but it is adding one additional copy of uploaded file. What is wrong?
My controller is like this:
public function add_audio(){
$config['upload_path'] = './musics/';
$config['allowed_types'] = 'mp3';
$config['max_size'] = '999999999999999999999';
$this->load->library('upload',$config);
$this->upload->do_upload();
if ( ! $this->upload->do_upload())
{
$data['error'] = $this->upload->display_errors();
print_r($data['error']);
//line of codes that displays if there are errors
}
else
{
$data['audio'] = $_FILES['userfile']['name'];
$this->load->model('main');
$query = $this->main->insert('audio',$data);
if($query == TRUE){
$this->load->view('admin/success');
}
}
... but it is adding one additional copy of uploaded file. What is wrong?
That's because you're calling do_upload() twice...
public function add_audio()
{
....
$this->upload->do_upload(); // <- FIRST upload (remove this one)
if ( ! $this->upload->do_upload() ) // <- SECOND upload
{
....
Since you may need the conditional logic that handles upload failures, delete the first instance of do_upload().
I am having a spot of trouble with Codeigniter and getting files to rename within the upload process from the Upload Library it has to offer. Now before anyone says it, I am not looking for "encrypted" file names.
My Problem is in uploading images you have a good handful of types you could be dealing with. So how does one change the file name using the file_name config option to a specific schema (which I already have the schema part up and working). But maintain the same file type?
Right now I am attempting
$upload_config['file_name'] = $generated_filename_from_schema
Only problem is $generated_filename_from_schema doesnt have a file extension, and leaving the file extension out of the equation CI seems to ignore it altogether and just takes the file and append_1, _2, _3 as it goes up if the files have the same name, otherwise it just leaves the name intact.
Now I have to pass the $config to CI so it will upload the file, but how can I determin what kind of file I am working with before it trys to upload so I can use my name generation schema.
*edit*
$upload_config['upload_path'] = realpath(APPPATH.'../images/');
$upload_config['allowed_types'] = 'gif|jpg|png';
$upload_config['max_size'] = 0;
$upload_config['max_width'] = 0;
$upload_config['max_height'] = 0;
$upload_config['remove_spaces'] = true;
$upload_config['file_name'] = $this->genfunc->genFileName($uid);
if($this->input->post('uploads'))
{
$this->load->library('upload');
$this->upload->initialize($upload_config);
if (!$this->upload->do_upload())
{
//echo 'error';
echo $config['upload_path'];
$this->data['errors'] = $this->upload->display_errors();
}
else
{
//echo 'uploaded';
$this->data['upload_data'] = $this->upload->data();
}
}
You can use $_FILES array to get original name of file.
Extract extension of original file.Then, append to your new file name.
Try as below
$ext = end(explode(".", $_FILES[$input_file_field_name]['name']));
$upload_config['file_name'] = $this->genfunc->genFileName($uid).'.'.$ext;
Personally, I find CodeIgniter's file uploading class to be somewhat cumbersome. If you want a vanilla PHP solution:
function submit_image(){
$f = $_FILES['image'];
$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($f['tmp_name']);
if(in_array($detectedType, $allowedTypes)){
$pi = pathinfo($f['name']);
$ext = $pi['extension'];
$target = $this->genfunc->genFileName($uid) "." . $ext;
if(move_uploaded_file($f['tmp_name'], $target)){
/*success*/
}
else {/*couldn't save the file (perhaps permission error?*/}
}
else {/*invalid file type*/}
}
//uploading product movie or image?
if($this->input->post('upload_360') == "Upload") {
$config['upload_path'] = './media/images/products/360s';
$config['allowed_types'] = 'swf';
$this->load->library('upload', $config);
$this->upload->initialize($config);
if (!$this->upload->do_upload('film')) {
$this->data['product_error'] = $this->upload->display_errors();
$this->template->build('/admin/products/create', $this->data);
} else {
$this->data['data_360'] = $this->upload->data();
$this->session->set_userdata(array('360_film' => $this->data['data_360']));
$this->template->build('/admin/products/create', $this->data);
}
$this->session->set_userdata(array('advantages' => $this->input->post('product_advantages')));
$this->data['session_advantages'] = $this->session->userdata('advantages');
}
//upload the product image, if successful the user will be
//notified if the image is too high or wide, and will be offered,
//the chance to crop the image. All cropping takes place in the media
//controller.
if($this->input->post('product_image') == "Upload") {
$config['upload_path'] = './media/images/products/';
$config['allowed_types'] = 'gif|jpg|jpeg|png';
$this->load->library('upload', $config);
$this->upload->initialize($config);
if (!$this->upload->do_upload('image_upload')) {
//die("!");
$this->data['image_error'] = $this->upload->display_errors();
$this->template->build('/admin/products/create', $this->data);
} else {
$this->data['image_data'] = $this->upload->data();
$this->session->set_userdata(array('image' => $this->data['image_data']));
$this->data['session_image'] = $this->session->userdata('image');
$this->template->build('/admin/products/create', $this->data);
}
$this->session->set_userdata(array('advantages' => $this->input->post('product_advantages')));
$this->data['session_advantages'] = $this->session->userdata('advantages');
}
if($this->input->post('screenshot_upload') == "Upload") {
$config['upload_path'] = './media/images/products/360s/screenshots/';
$config['allowed_types'] = 'gif|jpg|jpeg|png';
$this->load->library('upload', $config);
$this->upload->initialize($config);
if (!$this->upload->do_upload('screenshot')) {
//die("!");
$this->data['screenshot_error'] = $this->upload->display_errors();
$this->template->build('/admin/products/create', $this->data);
} else {
$this->data['screenshot_data'] = $this->upload->data();
$this->session->set_userdata(array('screenshot' => $this->data['screenshot_data']));
$this->data['session_screenshot'] = $this->session->userdata('screenshot');
$this->template->build('/admin/products/create', $this->data);
}
$this->session->set_userdata(array('advantages' => $this->input->post('product_advantages')));
$this->data['session_advantages'] = $this->session->userdata('advantages');
}
On my form I have the user choose a file and the click an upload button dependent on which button is clicked the file gets uploaded and the upload data gets saved in a session.
The session is then used to get data from to save to a database, the upload_360 session works, the product_image session works fine but the screenshot_upload session only has data when with the if statement (3rd one in the code) if I try and acccess it outside of the code then that portion of the session is empty?
Is there a reason for this?
Why are you storing data in a session before inserting it into the db?
Cookies can only hold 4KB of data...
but the screenshot_upload session only has data when with the if statement (3rd one in the code) if I try and acccess it outside of the code then that portion of the session is empty?
I don't understand that part of your question. Do you mean it only has data when only using the 3rd if statement? i.e. when only trying to do screenshot_upload and not product_image or 360_upload`? If so, that might speak to the cookie size limit.
Instead of
$this->session->set_userdata(array('screenshot' => $this->data['screenshot_data']));
$this->data['session_screenshot'] = $this->session->userdata('screenshot');
why don't you
$this->uploads_model->insert_screenshot_data($this->data['screenshot_data']);//send screenshot upload_data to model to be inserted into db
$this->data['screenshot_data'] = $this->data['screenshot_data'];//if you want to pass screenshot upload_data to template/view
?
It looks like you are sending output to the user before setting the session (I'm inferring this from the $this->template->build, which is custom code.)
The session, like headers, cannot be modified after anything (ANYTHING) has been sent to output. This is because the session itself is sent in the header.
I'm trying to do something very simple but I can't see to make it work. For what it's worth, I'm currently testing on my MAMP dev machine, but get the same results from staging server (GoDaddy GridHost).
Here's what I want to do:
Upload an image specified by the user from a form.
Create a thumbnail of the uploaded image.
There is some extra database code in my example, but the script "errors" at the if( ! $this->image_lib->resize()) call. However, it causes the entire application to exit, rendering a blank page. The code never actually enters the if{} block.
function _upload_image(&$location, &$image = NULL)
{
// Configure the initial full-sized image upload
$upload_config = array(
'upload_path' => "./uploads/users/{$this->viewer->id}/locations/{$location->id}/",
'allowed_types' => 'jpg|jpeg|gif|bmp|png',
'max_size' => 8192 // 8mb
);
$this->load->library('upload', $upload_config);
// Upload failed
if( ! $this->upload->do_upload('image'))
{
$this->errors = strip_tags($this->upload->display_errors());
return FALSE;
}
// Get the uploaded file's metadata
$data = $this->upload->data();
// Change permissions of the uploaded file so that the image library can copy and resize it
if(is_file($config['upload_path'] . $data['file_name']))
{
chmod($config['upload_path'] . $data['file_name'], 0777);
}
// If no existing image object was passed to this function, we are creating a brand new image
if(is_null($image))
{
$image = new Image();
$thumbnail = new Thumbnail();
}
else
{
$thumbnail = $image->thumbnail->get(); // Get the existing thumbnail
}
// Set the image object fields to save to the db
$image->name = $data['file_name'];
$image->mime_type = $data['file_type'];
$image->extension = $data['file_ext'];
$image->file_path = $data['file_path'];
$image->full_path = $data['full_path'];
$image->size = $data['file_size'];
$image->width = $data['image_width'];
$image->height = $data['image_height'];
// Failed to save the image to the db
if( ! $image->save())
{
$this->errors = array_merge($this->errors, array($image->error->string));
return FALSE;
}
// Failed to save the location/image relationship in the db
if( ! $location->save($image))
{
$this->errors = array_merge($this->errors, array($location->error->string));
return FALSE;
}
// Configure options for the thumbnail
$thumb_config = array(
'image_library' => 'GD2',
'source_image' => "./uploads/users/{$this->viewer->id}/locations/{$location->id}/{$image->name}",
'create_thumb' => TRUE,
'width' => 400,
'height' => 300
);
$this->load->library('image_lib');
$this->image_lib->initialize($thumb_config);
// Failed to create the image thumbnail
if( ! $this->image_lib->resize())
{
$this->errors = array_merge($this->errors, array($this->image_lib->display_errors()));
return FALSE;
}
// Set the thumbnail object fields to save to the db
$thumbnail->name = $data['raw_name'] . '_thumb' . $data['file_ext'];
$thumbnail->file_path = $image->file_path;
$thumbnail->full_path = $image->file_path . $thumbnail->name;
// Failed to save the thumbnail to the db
if( ! $thumbnail->save())
{
$this->errors = array_merge($this->errors, array($thumbnail->error->string));
return FALSE;
}
// Failed to save the image/thumbnail relationship in the db
if( ! $image->save($thumbnail))
{
$this->errors = array_merge($this->errors, array($image->error->string));
return FALSE;
}
// Everything worked
return TRUE;
}
The database interaction is handled by the DataMapper ORM, which I included for completeness, but I don't feel it is necessarily relevant to this issue. The function clearly fails at the call:
if( ! $this->image_lib->resize())
Have you set your application environment in the index.php bootstrap? It's worth setting it to development if you haven't already, this may make errors visible that would be hidden if set to testing/production.
define('ENVIRONMENT', 'development');
If that doesn't help diagnose the issue, in MAMP, go to the Server tab, click PHP and then View Log. This will open up the PHP error log file which will hopefully give you an idea of what's up.