codeigniter image uploading mysql - database

I wanted to know if I was uploading an image in CodeIgniter to a database what would be my
$config['upload_path']
All the examples I have seen are using the filesystem. I have articles in a db and would like to store images relating to articles in the db as well. Can anyone help?

You can read this great article called Storing Images in Mysql.
The article covers the following:
Isn’t this a bad idea?
What is a BLOB?
Creating an image table
The upload form
Uploading the image
The upload() function
Display an image from the database
Displaying all the information
But not to leave you empty handed, look into Blob, it's a data-type for colums in MySQL ( and various other dbms ). This will let you store data such as Images and other binary file-types.
The idea of storing files and images in the database is in general the same as storing them on the filesystem, the layer in-between upload and having the actual file is just different.
You cannot just set your upload-path and hope everything is solved, you need to get some dirt on your hands aswell!

i posted here in hope this help someone since this is an old post and the answers are no help at all, this code works for me, also the model part is not here so you must figure it out reading codeigniter's docs , i think this will work if you put it in your controller, also it think the submit form must be pointing this function
function upload() {
$caption = $this->input->post('caption');
$codigo = $this->input->post('codigo');
//$imagen = $this->input->post('imagen');
$config['upload_path'] = 'uploads';// this is a directory with 777 permissions where you upload the file
$config['allowed_types'] = 'gif|jpg|jpeg|png|pdf';
//$config['max_size'] = '5000';
$this->load->library('upload', $config);
if (!$this->upload->do_upload('imagen')) { // this is the input from the form
echo $this->upload->display_errors();
} else {
//here $file_data receives an array that has all the info
//pertaining to the upload, including 'file_name'
$file_data = $this->upload->data();
$fp = fopen($file_data['full_path'], 'r');
$content = fread($fp, filesize($file_data['full_path']));
//$content = addslashes($content);
fclose($fp);
$data = array( // this is the table i got in my db
'idBotones' => null,
'imagen' => $content, //blob image
'caption' => $caption,
'codigo' => $codigo
);
$this->load->model('generic_model');
$table = "botones";
$this->generic_model->insertar_datos($table, $data);
//print_r($content);
}
}

It seems like for most common use cases storing images in the database is not a great idea.
Please see these two previous SO threads:
To Do or Not to Do: Store Images in a Database
Storing Images in DB - Yea or Nay?

Related

Symfony2 simple file upload edit without entity

Please help me out here because I can't belive my eyes.
I refuse to use some 3rd party plugin for file uploads, and refuse to creat a separate entity for a file/document. I just want simple file upload that I would do in Zend/Laravel and so on.
I have a invoice table with the last collumb name "attachment", I want to store here its sanitized name (eg: 123421_filename.jpg ), the addition form and upload went well.
code here:
//AddAction
$file=$form['attachment']->getData();
$fileName=$file->getClientOriginalName();
$sanitizedFilename=rand(1, 99999).'_'.$fileName;
$dir='files/'.$userId.'/';
$file->move($dir, $sanitizedFilename);
...
$invoice->setAttachment($sanitizedFilename);
$em = $this->getDoctrine()->getManager();
$em->persist($invoice);
First problem I have and don't know how to solve is using the edit form.. I have a formbuilder
$builder->add('attachment', 'file',array('data_class'=>null))
Because I don't have a "Object" for my file and because in my invoice table I store the name as a string, I get an error here and I need to force the data_class => null .. which is bad, because if I edit a Invoice in the frontend for the upload field I get NULL, instead of the filename of the current file linked to the invoice.
With:
$builder->add('attachment', 'text')
I don't get the file input just a silly textbox BUT THIS TIME --with the name in it-- .. so how do I solve this? File Input widget and file name in it without a Document object ?!
And the second question ( I am merely at the point of throwing out all my application developed until now and move to laravel because I had a lot of "these kind of problems" ..doing simple things in symfony is almost always more complicated than in other frameworks..or maybe its my fault that I don't want to folow the guidelines and create a Document Entity?! What if I want flexibility and want to manage my database in another manner that doesn't fit in all these guidelines?)
So I am on the edit form action, I upload a new file (don't forget that I have the file set to $builder->add('attachment',file',array('data_class'=>null))
I can't get my attachment string name from the current invoice I am editing? !
public function editAction($id)
....
$invoice = $em->getRepository('AppBundle:Invoice')->find($id);
..
if ($form->isValid()) {
$oldFileName=$invoice->getAttachment(); //this is null
$oldFileName=$invoice->getId(); //this returns the invoice id
$oldFileName=$invoice->getValue(); //returns invoice value
echo 'old: '.$oldFileName.'<br/>';
exit();
}
So someone please tell me why I can't access my invoices property? Which is a string ?
I tried making a new instance I though that somehow if I create the form with the $invoice object it somehow links him to the attachment from the edit form
if ($form->isValid()) {
$sameInvoice= $em->getRepository('AppBundle:Invoice')->find(20); //hardcoded ID
$oldFileName=$sameInvoice->getAttachment(); //still null
$oldFileName=$sameInvoice->getId(); //returns 20
echo 'old: '.$oldFileName.'<br/>';
exit();
The only thing I wanted was, have a filename string in my invoice table, and test myself if the file exists in the path with that filename and if it exists, then delete it and upload the new one and so on.. why does it have to be so hard ??
Why do I have to create a entity ? Why do I have to alter my database structure (its not the case here..but what if the client doesn't want the database to be changed..so I can't insert this "Document" table).. Why can't the form builder show the data from invoice->attachment, I get it that because he needs a file data and he can't accept a string, but why aren't there guidelines for these simple tasks?!
Alright I finally managed to get it working:
So the problem why it was NULL was because it did bind the $invoice instance to the form:
$invoice = $em->getRepository('AppBundle:Invoice')->find($id);
$form = $this->createForm(new InvoiceType($id), $invoice);
After this block of code, all refferences like : $invoice->getAttachment();
Are reffered to as the form invoice object not the actual object, so basically after this I can only call things like: "getClientOriginalName()" and would show me the new file that I uploaded in the edit form.
To counter this I created a variable that stores that name initially before the $invoice object to get bind to the form
$invoice = $em->getRepository('AppBundle:Invoice')->find($id);
$oldFileName=$invoice->getAttachment(); //this is stil the object here I can see the record from the database
$form = $this->createForm(new InvoiceType($id), $invoice);
//here the $invoice->getAttachment(); returns null
So now I have the old name and I can test it like:
if ($form->isValid()) {
$fs=new Filesystem();
$newFile=$form['attachment']->getData();
$newFileName=$newFile->getClientOriginalName();
if($newFileName != $oldFileName)
{
// if($fs->exists('files/'.$this->getUser()->getId().'/'.$oldFileName))
// $fs->remove('files/'.$this->getUser()->getId().'/'.$oldFileName);
$sanitizedFilename=rand(1, 99999).'_'.$newFileName;
$dir='files/'.$this->getUser()->getId().'/';
$newFile->move($dir, $sanitizedFilename);
$invoice->setAttachment($sanitizedFilename);
}
$em->persist($invoice);
$em->flush();
return $this->redirect($this->generateUrl('my-invoices'));
}
For the other problem with the filename of the old file not appearing in the Edit Invoice Page I sent my variable to the view :
return $this->render('AppBundle:Invoices:edit.html.twig', array(
'oldFileName' => $oldFileName)
And put that value to the label of the input file widget using twig
Remain calm. You are making this much harder then it needs to be.
myControllerAction()
{
// No need for an object, an array works fine
$model = array(
'invoice' => $invoice,
'attachment' => null
);
$builder = $this->createFormBuilder($model);
$builder->setAction($this->generateUrl('cerad_game_schedule_import'));
$builder->setMethod('POST');
$builder->add('attachment', 'file');
$builder->add('invoice', new InvoiceType());
$builder->add('import', 'submit', array(
'label' => 'Import From File',
'attr' => array('class' => 'import'),
));
$form = $builder->getForm();
$form->handleRequest($request);
if ($form->isValid())
{
$model = $form->getData();
$file = $model['attachment']; // The file object is built by the form processor
if (!$file->isValid())
{
$model['results'] = sprintf("Max file size %d %d Valid: %d, Error: %d<br />\n",
$file->getMaxFilesize(), // Returns null?
$file->getClientSize(),
$file->isValid(),
$file->getError());
die($model['results'];
}
$importFilePath = $file->getPathname();
$clientFileName = $file->getClientOriginalName();
// Xfer info to the invoice object and update
}

Laravel 4 not getting JSON from input Backbone.js

I have read and worked with the other posts about this and it appears the version of Laravel 4 I just downloaded has more changes made to the way the JSON input is handled by a controller.
$input = Input::json()->all(); gives me errors as if I am referring to something that does not exist when I request some part of the payload after doing a PUT request. And without ->all(); I get a symfony error.
Does anyone know how to get good JSON from backbone in Laravel 4's latest version?
Currently, I am doing the long way around to get my data, ie:
$input_title = Input::get('title');
$input_completed = Input::get('completed');
$task = Task::find($id);
$task->title = $input_title;
$task->completed = $input_completed;
$task->save();
Yes, I am doing the tutorial on tutsplus to learn laravel/backbone, so a little noob patience is apreciated.
The error I get when using Input::get(); is:
{"error":{"type":"UnexpectedValueException","message":"The Response content must be a string or object implementing __toString(), \"array\" given.","file":"/Users/brentlawson23/Sites/laravel4App/bootstrap/compiled.php","line":16858}}
I really want to get the Laravel-specific answer instead of using straight php to stringify the payload.
I get same error using just Input::json();
For the current beta of Laravel 4, Input::json(); is not getting a stringified version of the request payload that can be used to create a new row in a table, nor does Input::json()->all(); (hoping to play nice with the ParameterBag from symfony). I have tried json_encode among other hacks and basically every step of the way in this tut, I hit some brick wall. Anyone have a suggestion based on what I have presented here?
Today I got this when simply trying to echo the result of $input = Input::json(); :
{"error":{"type":"ErrorException","message":"Catchable Fatal Error: Object of class Symfony\Component\HttpFoundation\ParameterBag could not be converted to string in /Users/brentlawson23/Sites/laravel4App/app/controllers/TasksController.php line 45","file":"/Users/brentlawson23/Sites/laravel4App/app/controllers/TasksController.php","line":45}}
Yes, I have studied the Symfony API.
I had a similar problem. Input from Backbone is converted to array in Laravel. On tutsplus, Jeffrey Way is using object. So I was trying to do this (like in tutorial):
return $input->title // using object,but got an error.
If I change that line to:
return $input["title"] // everything works fine with array.
I'm also working through the Backbone tutorial on tuts+. If I'm right in assuming are you stuck on the Creating New Contacts section? Below is how I got it to work for me, in ContactController.php:
public function store()
{
$input = Input::all();
Contact::create(array(
'first_name' => $input['first_name'],
'last_name' => $input['last_name'],
'email_address' => $input['email_address'],
'description' => $input['description']
));
}
And then also needed to update app/models/Contact.php with the below:
class Contact extends Eloquent {
protected $fillable = array('first_name', 'last_name', 'email_address', 'description');
}
That should get it working for you and insert the contact into the database. If I've misread let me know and I can have another look.
Cheers,
Sean

Multiple models and uploading files

At first - I'm new to the Yii Framework. I did some research on my own but I couldn't find a precise solution to my issue.
Assume there are two related models - Product and Image. A single Product may have multiple Images assigned. What is the best approach at creating the create / update forms that would be able to manage this kind of scheme?
The Image model consists of various fields, along with a path to the image file, so it's not just a "container" for the path itself. What's more - I need to have a thumbnail generated for every uploaded image and its path stored within the same model.
What I need to achieve is pretty much similar to the admin inline functionality known from Django - there should be a section in the Product create / update form which would allow users to add / modify / delete Images.
I tried the multimodelform extension but I couldn't get file uploading to work. What's the best way of getting it done and not having to build the whole file-upload-enabled-multiple-model-form structure manually?
The detailed solution depends on if you are using CActiveForm or CHtml form. Since you have 2 related models I assume you are using CActiveForm and will point out some thing you need to keep in mind.
For this example i am gonna assume some definitions
Product with fields id, name
Product with ONE to MANY relation to 'images' on ProductImage
ProductImage with fields id, productId, path
I also assume there gonna be 1 upload / edit, but multi delete
Here's the view:
$form = $this->beginWidget(
'CActiveForm',
array(
'id' => 'upload-form',
'enableAjaxValidation' => false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)
);
echo $form->labelEx($product, 'name');
echo $form->fileField($product, 'name');
echo $form->error($product, 'name');
echo $form->checkBoxList($product, 'path', $product->images);
echo $form->labelEx($productImage, 'path');
echo $form->fileField($productImage, 'path');
echo $form->error($productImage, 'path');
$this->endWidget();
And your action
public function actionUpdate($productId) {
$product = Product::model()->findByPk($productId)->with('images');
$productImage = new ProductImage();
if(isset($_POST['Item']))
{
$product->attributes=$_POST['Product'];
foreach($product->images as $im) {
if(in_array($im->path, $_POST['Item']['Image']))
$im->delete();
}
$productImage->image=CUploadedFile::getInstance($productImage,'path');
if($productImage->save())
{
$productImage->image->saveAs('some/new/path');
// redirect to success page
}
}
$this->render('update', array(
'product'=>$product,
'productImage'=>$productImage,
));
}
Now note that this solution is not tested so there will be bugs, but it should give you an idea on how to write your own form.
Resources:
http://www.yiiframework.com/wiki/2/how-to-upload-a-file-using-a-model/
http://www.yiiframework.com/wiki/384/creating-and-updating-model-and-its-related-models-in-one-form-inc-image

unable to retrieve image from custom content type

I've just started learning how to use Drupal 7. I made a new content type that will be displayed as a feed in my front page. All the data I need are being fetched and displayed correctly except for the image, whose url is always missing the actual file. I have another feed in my front page that uses the default article content type and all the images display properly.
The code I used for both is essentially the same, the only difference being the content type being retrieved.
This set worked:
$query = db_select('node', 'n');
$query->fields('n', array('nid', 'title'))
->condition('n.type', 'article')
->leftJoin('field_data_body', 'u', 'u.entity_id = n.nid');
$query->addField('u', 'body_summary');
$query->orderBy("nid", "desc");
$query->range(0, 3);
$result = $query->execute();
while($row = $result->fetchAssoc()) {
$nid = $row['nid'];
$node = node_load($nid);
echo theme('image_style', array('style_name' => 'home-article-summary', 'path' => ($node->field_image['und'][0]['uri'])));
}
This didn't:
$query = db_select('node', 'n');
$query->fields('n', array('nid', 'title'))
->condition('n.type', 'news') //the only difference between the two is this line
->leftJoin('field_data_body', 'u', 'u.entity_id = n.nid');
$query->addField('u', 'body_summary');
$query->orderBy("nid", "desc");
$query->range(0, 3);
$result = $query->execute();
while($row = $result->fetchAssoc()) {
$nid = $row['nid'];
$node = node_load($nid);
echo theme('image_style', array('style_name' => 'home-article-summary', 'path' => ($node->field_image['und'][0]['uri'])));
}
I tried making the settings of the content type I created the same as the ones for article throught Structure->Content Types but nothing happened. What am I missing? Thank you.
edit:
Upon inspection, I couldn't find a resized version of the image I uploaded for my custom content type. I'm assuming this means no resizing ever actually happened hence why the script didn't return a file. I still don't get why that happened.
edit the second:
never mind. I found the problem. it's all working fine now. was just using the wrong variable.
As a bit of friendly advice for a Drupal newcomer, consider using Views to display lists of content instead of writing heaps of custom database queries. That will save you lots of coding in the long run.
Another argument for Views is that it's going to be included in Drupal 8 core.

CakePHP user session not updating but database yes

I'm developing with cakePhP and I have the following problem:
When a user logs in with his name and password to the account system that I've created, he can save items (images) as favorites. This is saved in a text field into the database. What is saved is the image ID.
The saving process works perfectly, the user clicks on the images and they're added to that field (it actually saves all the IDs as a text array that I process later).
The problem comes when removing images. When the user does it (I'll post the code below), the images is removed correctly from the database (I go to PHP MyAdmin and I see it). This means that the array that holds the favorite images IDs is updated instantly. However, when I reload that array from the website, it hasn't been updated. It's like it's stored in the caché or something. Then, if the user logs out and logs in again, then he can see the correct one. The thing is that I have other things in my website that work in a similar way and they all get updated instantly, so I can't see why this doesn't.
This is the code that I use to remove the ID from the database:
function remove_favorite($pictureID) {
$this->User->id = $this->Auth->User('id'); //We get the ID of the current user
$favoritesArray = $this->User->deleteFavoritePicture($this->User->id, $pictureID); //This function retrieves the array (string) of pictures from the user's table, and deletes all the images with the ID passed as parameter, returning the updated array (string)
$fields = array('images_favorites' => $favoritesArray, 'modified' => true); //We indicate the field that we're going to update in the users table
//We save the new string that doesn't contain the deleted image anymore
if($this->User->save($fields, false, array('images_favorites'))) {
$this->Session->setFlash(__('The image has been removed from your favorites', true));
} else {
$this->Session->setFlash(__('Error removing image from favorites, please try again', true));
}
$this->redirect(array('action' => 'manage_favorites',$this->User->id));
}
This is how the deleteFavoritePicture function looks like:
function deleteFavoritePicture($userID, $pictureID) {
$userInfo = $this->find("id = $userID");
$favoritePicturesString = $userInfo['User']['images_favorites'];
$favoritePicturesArray = explode(",", $favoritePicturesString); //Array
$i = 0;
while ($i < count($favoritePicturesArray)) {
//We remove from the array the images which ID is the one we receive to delete
if ($favoritePicturesArray[$i] == $pictureID) unset($favoritePicturesArray[$i]);
$i++;
}
$favoritePicturesString = implode(",", $favoritePicturesArray); //String
return ($favoritePicturesString);
}
That's it. Does anyone now what can be going on? Thanks so much in advance for any clue!
EDIT
Ok, I think I found something that may give a clue of what's going on here:
This is the code for the manage_favorites action:
function manage_favorites($id) {
//$user = $this->User->find("id = $id");
$user = $this->Auth->user();
$this->set('user', $user);
}
That is the action that is called for the page when a user wants to modify his favorites. The same action is called once the user removes a favorite. Here's the thing:
If I use the $id parameter in the manage_favorites function and the $user = $this->User->find("id = $id"); line (the one quoted now), then the problem does not exist! This is how I used to have it. HOWEVER, I had to change it because it was a big security flaw, since the user id ($id) was a visible parameter who anyone could change, and then access other users accounts. What I did was changing the way I obtain the user array of favorite images, using the following line: $user = $this->Auth->user();. This is how I have it now (well, and also without the $id parameter in the function header), so the user information (including the favorites array) comes from the Auth component, instead directly from the database.
So, the problem is clear: when the user deletes a favorite, it's doing it on the array in the database. WHen I show the result of that operation, the array I'm retrieving is not the one in the DB, it's the one in the session. That's why it's not showing the changes.
How can I avoid this without using a non-secure method like the one I had before?
When you save, the array passed to the save method of the model should look like this:
[User] => array(
[field] => value,
[field2] => value2,
...
)
In your example, you clearly haven't added the [User] key.
Also, is your modified field actually the default Cake modified field? That is, the DATETIME field which changes to the current time when the row is updated?
Lastly, maybe you have debugging set to 2 in config.php. try changing this to 0 (as in production) and see if caching persists.
Hope some of the points I have mentioned above will solve your problem. Please let me know!
There could be two things wrong with this.
What does your deleteFavoritePicture method look like? There could be something being done wrong there.
You're passing false as the second parameter to the User::save method, which means that you don't want to validate. Unless there is a SQL error, then this will return true even if it doesn't validate properly, I believe. Try changing this false to true and see if your results differ.

Resources