After I had checked the questions here, I saw that I need write_file for text writing to a .txt file. I also looked for a tutorial or an example about it on Google but couldn't find a simple one.
Could you explain me basically about how to write something to a .txt file in Codeigniter?
As an example, a text is submitted by a user on a registration form and then the text written by the user, will be shown in users.txt.
From the documentation:
$this->load->helper('file');
$data = 'Some file data';
if ( ! write_file('./path/to/file.php', $data))
{
echo 'Unable to write the file';
}
else
{
echo 'File written!';
}
There is a file helper in codeIgniter called file_helper.php in system/helpers that will help you do that :
$this->load->helper('file');
$data = 'My Text here';
if ( !write_file('./path/to/file.txt', $data)){
echo 'Unable to write the file';
}
Full documentation about file_helper is here.
Related
Currently have working on an image upload in a Laravel/Inertia/React stack.
Issue: It currently works using a symbolic link to the public folder. This is no good as it means anyone can access the images if they have the link. How can I do this differently so that only the owner of the image can view it?
Displaying the image:
<img src={`/storage/${props.company.logo_filename}`}/>
Storing the logo:
public function storeLogo(Request $request)
{
$company = auth()->user()->company();
$logo = $request->file('logo');
$extension = $logo->getClientOriginalExtension();
Storage::disk('public')->put($logo->getFilename() . '.' . $extension, File::get($logo));
dd(Storage::url('public/'. $logo->getFilename()));
$company->logo_mime = $logo->getClientMimeType();
$company->logo_original_filename = $logo->getClientOriginalName();
$company->logo_filename = $logo->getFilename() . '.' . $extension;
$company->save();
//DELETE old Logo if exists
return Redirect::back()->with(
'message',
[
'type' => 'success',
'text' => 'Logo Updated'
]
);
}
note: In this particular scenario (company logos) I'm aware that it probably doesn't matter if someone else gets access to the images. Please just assume they are sensitive.
You could add a route to serve the files and check if the current user is allowed to access the file.
use Illuminate\Support\Facades\Storage;
Route::get('files/{filename}', function (string $filename) {
// Do your magic to check if the current user is allowed to access that file
// Do your magic to determine the full path of the file
$fullPath = '/some/directory/' . $filename;
// Once we have the full path we can stream the contents of the file to the client
return Storage::response($fullPath);
});
Unfortunately the Storage::response() method is undocumented as far as I know, but you can find it's implementation here:
https://github.com/laravel/framework/blob/5.5/src/Illuminate/Filesystem/FilesystemAdapter.php
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
}
$image_name = $this->data['ApkCollection']['apk_image']['name'];
echo $image_name; // it show result as number like 7 or 3 etc...
when am upload image in edit.ctp file means it show image name as above result, but it works fine on add.ctp file
Someone help me...
Is your code from the controller or view (edit.ctp)? If you're inspecting the posted data in the controller, what does this show?
pr($this->request->data['ApkCollection']['apk_image'])
If it's in the view, wouldn't it just be this?
$image_name = $this->data['ApkCollection']['apk_image'];
echo $image_name;
The file details array (that 'name' is part of) only exists as the result of a post, I think.
Toby
I want to edit a record in CakePhp without deleting the saved path of an uploaded jpg file. Right now when I edit the record it deletes the saved file path.
The approach I think would work is to do a logic check in the form to check if the field is empty or not. Display the saved file path if it's not empty or show an empty path if it is. Would this be the best way to update the record?
I'm using Miles Johnson's uploader plugin for uploading files.
Here's the code within the form:
<?php
if (!empty ($slider ['Slider']['bgImg']));
echo $slider ['bgImg'];
else
echo $form->input('file', array('type' => 'file'));
?>
This logic should be in the controller, strictly speaking.
In my apps with files and edit capabilities, I will show a file field and a link/thumbnail of the image in question on the edit form.
my approach uses my own uploader, so your results may vary, but essentially:
if (!empty($this->data)) {
$file_object = $this->data['Listing']['featured_image'];
$image_data=$this->Upload->do_upload($file_object, 'img/uploads/');
if($image_data){
$this->data['Listing']['featured_image'] = $image_data['name'];
} else {
unset($this->data['Listing']['featured_image']);
}
$this->Listing->save($this->data)
and in my upload component, I have this:
public function do_upload($file_object, $location='img/uploads/') {
/**
* No file was uploaded
*/
if($file_object['error']==4) {
return false;
}
// carry on uploading
So essentially; I pass my upload component the $file_object, which is from the form. I then do a simple test, using the default set of error codes to see if the file is empty (4). If it's empty, I return false. (you could return errors etc, but this was my approach).
after the upload call, I check the return value, and if the file was uploaded successfully, I can then set the field in my model. (the file name, in my case) - you may want to store the path as well, for instance.
If it's false - it means there was no file; so I unset the value from the array.
Because the field does not exist in the array, cake will not attempt to overwrite existing data - it simply ignores it; allowing the old value to stay untouched.
I'm new to cakephp and I have found this milesjohnson's upload plugin ,
and I kind of like it, mostly because it gives me the chance of renaming the file once uploaded.Unfortunately, I can't get it to upload any zip/rar files.
This is the action where I upload the file:
function add() {
if (!empty($this->data)) {
if ($data = $this->Uploader->upload('link_referencia', array('name' => date("dmYhis")))) {
debug($data);
$this->data['Publicacione']['link_referencia']=$data['name'];
}
$this->Publicacione->create();
if ($this->Publicacione->save($this->data)) {
$this->Session->setFlash(__('The publicacione has been saved', true));
//$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The publicacione could not be saved. Please, try again.', true));
}
}
$users = $this->Publicacione->User->find('list');
$this->set(compact('users'));
}
And this is the error I get everytime I attempt to upload any zip/rar file :
EDIT
Full insert query:
INSERT INTO `publicaciones` (`vigencia`, `tipo`, `titulo`, `descripcion`, `fecha_publicacion`, `fecha_caducidad`, `link_referencia`, `modified`, `created`) VALUES (1, 'c', 'there\'s nothing you can\'t do', '
fsdfsdfsdf
', '2011-06-07', '2011-06-30', Array, '2011-06-07 16:47:23', '2011-06-07 16:47:23')
Does anyone have any ideas on what the problem might be?
Thanks in advance.
i think there is nothing with the code what you have written but you should look at in to the plugin and find out whether it gives permission you to upload zip or not.
there will be conditions in your pluggin that you can upload only some kind of files like jpg,png,txt something like that.
I hope that helps you.
Regards,
Archit
Are you totally sure your File input on the form has type=>file specified, and same for your form?
Also I would look at other uploaders - MeioUpload can allow renaming and so on and is a bit more up to date. There is also the Cuploadify plugin (uploadify for cake) you can find on github.
Make sure your form is set to multipart/form-data like so:
<?php echo $this->Form->create('File', array('enctype' => 'multipart/form-data')); ?>
The following code will upload a file:
if ($this->request->is('post')) {
if ( $this->data['File']['file']['error'] <= 0 && $this->data['File']['file']['size'] <= 8388608 ) { // Check for no errors and that File size is around 8mb.
$folder = new Folder (ROOT . DS . 'app' . DS . 'filestorage' . DS, true); // create folder in /app/filestorage/
$path = $folder->path . $this->data['File']['file']['name']; // Set path to newly created folder + uploaded file name.
$tmpUrl = new File ( $this->data['File']['file']['tmp_name'] ); // Create temporary file object
if ($tmpUrl->copy($path , true) ) { // If copying file to path is successful,
$this->Session->setFlash(__('File uploaded succesfully!'));
}
}