I have debian machine and my site is in /var/www/laravel-site/ folder.
In laravel-site folder i have FILES and PUBLIC folders. How can i output file to FILES folder to protect the file from web reading?
I guess base_path() will help
Simple usage example:
<?php
$file = base_path('FILES').'/people.txt';
// Open the file to get existing content
$current = file_get_contents($file);
// Append a new person to the file
$current .= "John Smith\n";
// Write the contents back to the file
file_put_contents($file, $current);
?>
function base_path($path = '') is a Laravel helper function. It gets the path to the base of the install:
function base_path($path = '')
{
return app()->basePath().($path ? '/'.$path : $path);
}
So, to get your /var/www/laravel-site folder just use
echo base_path();
To get FILES folder (or whatever path you need inside the Laravel's base) use echo base_path('FILES');
it will output /var/www/laravel-site/FILES
Related
In my Laravel 5.5 project I am having a problem in showing uploaded files. I uploaded the files using Storage. The part of store action of the controller is indicated below.
if ($request->hasFile('content_uz'))
{
$path = $request->file('content_uz')->store('/content/lesson'.$topic->lesson->id.'/topic'.$topic->id);
$data->content_uz = $path;
}
if ($request->hasFile('content_ru'))
{
$path = $request->file('content_ru')->store('/content/lesson'.$topic->lesson->id.'/topic'.$topic->id);
$data->content_ru = $path;
}
Uploading happened successfully. The path to uploaded 'content_uz' file is stored with "storage/app/content/lesson2/topic3" path and content_uz column is stored in my db as below:
content\lesson2\topic3\WSjrlG9a1ermGDOvRJTjn9iEIhfFvhVzjaOs6l79.mp4
How can I display the files in my Blade template? I searched the web, but with no result.
You can use method like this,
public function showFile() {
header("Content-type: video/mp4");
return Storage::get($filePath);
}
I hope this will help.
You may access the files of storage directory by two ways.
If your files are publicly accessible then you may follow laravel public disk.
If your files are protected or private then you may declare a route to access the files.
Route::get('content/{lesson}/{topic}/{file}', function($lesson, $topic, $file)
{
//Check access logic
$filePath = '/content/' . $lesson . '/' . $topic . '/' . $file;
return Storage::get($filePath);
});
I have a simple function that gets a "Blob" file from the database and tries to download it to heroku "collections" folder. It is working in my local computer where it takes the blob file and downloads it to my local directory but the same method does not work in Heroku.
public function downloadCollectionFiles(){
$this->load->helper('file');
$root = dirname(dirname(__FILE__));
$root .= '/third_party/collections/';
$this->load->model('invoice_page');
$collectionData = $this->invoice_page->getCollectionTable();
foreach($collectionData as $data){
$invoiceName = 'xinvoices_xml'.'_'.date("Y-m-d").'_'.rand();
$paymentName ='updates_xml'.'_'.date("Y-m-d").'_'.rand();
if($data->invoice_xml){
file_put_contents($root.$invoiceName.'.xml', $data->invoice_xml );
}
if($data->payment_xml){
file_put_contents($root.$paymentName.'.xml', $data->payment_xml );
}
return true;
}
I have tried crazy amount of method, but it just does not download the file on a heroku folder called "collections"
The mysql stores this string as blob.
I have created one process to read information from files and save into database, everything works fine in my desenv environment, but when I have put files in my php host (production environment) the process fail when read files.
to execute my process, I have created one cron job on cpanel, whith the command bellow:
php -q /home/<hostfolder>/batch/index.php
When my process is executed by cron, the output say that don't have files. Bellow part of my code:
private $sourceFilesFolder = "/home/<host folder>/public_html/batch/arquivos";
private $destFilesFolder = "/home/<host folder>/public_html/batch/processados";
private $log;
private $trataException;
function __construct($log, $trataException) {
$this->log = $log;
$this->trataException = $trataException;
}
/**
* Read the source folder and select only files
* #return array - Array of valid files
*/
function selectFiles() {
// Save the first read of ftp folder
$listSourceFolder = scandir ( $this->sourceFilesFolder );
// Array tho save only valid files
$listFiles = array ();
// read the array with ftp content and save in listFiles only files
foreach ( $listSourceFolder as $file ) {
$verifica = $this->sourceFilesFolder . "\\" . $file;
// if is a file type, try save in listFiles array
if (($file != ".") && ($file != "..") && (!is_dir ( $verifica ))) {
// verifiy if the file exists
if (file_exists ( $verifica )) {
$this->log->gravaLog ( $file . " -> ADDED TO PROCESS" );
//verificaArquivoEmUso ( $verifica );
array_push ( $listFiles, $verifica );
} else
$this->log->gravaLog ( $file . "-> do not exist." );
} else
$this->log->gravaLog ( $file . "-> not is a file." );
}
return $listFiles;
}
In my folder I have two txt files and this appear in the $listSourceFolder variable, but when I check this files with file_exists, always return false.
First, I have put my code files in a bacth folder in /home/
In the second test, I move the files in ftp folder and put inside the bacth folder (same of my code).
In the third test, I moved all batch folder (with codes and txt files) to public_html folder.
Nothing work, always the same error, file not exists.
I tryed remove ths file_exists if, but occur erros on the next step of algoritm.
I have checked the file permissions, and all permissions are ok.
What is I can do???
You can try three things.
1 - chmod 777 (Give permission so php can read and write files)
2 - I know its practically impossible that your server has a lower version of php. Scandir only works php 5 above. So you might wanna check that.
3 - There's a module called "mod_speling", try put that on.
;)
It appears that you are using the incorrect path delimiter for *nix.
You might change your code to be the following instead:
$verifica = $this->sourceFilesFolder . "/" . $file;
I have uploaded a lot of images from the website, and need to organize files in a better way.
Therefore, I decide to create a folder by months.
$month = date('Yd')
file_put_contents("upload/promotions/".$month."/".$image, $contents_data);
after I tried this one, I get error result.
Message: file_put_contents(upload/promotions/201211/ang232.png): failed to open stream: No such file or directory
If I tried to put only file in exist folder, it worked. However, it failed to create a new folder.
Is there a way to solve this problem?
file_put_contents() does not create the directory structure. Only the file.
You will need to add logic to your script to test if the month directory exists. If not, use mkdir() first.
if (!is_dir('upload/promotions/' . $month)) {
// dir doesn't exist, make it
mkdir('upload/promotions/' . $month);
}
file_put_contents('upload/promotions/' . $month . '/' . $image, $contents_data);
Update: mkdir() accepts a third parameter of $recursive which will create any missing directory structure. Might be useful if you need to create multiple directories.
Example with recursive and directory permissions set to 777:
mkdir('upload/promotions/' . $month, 0777, true);
modification of above answer to make it a bit more generic, (automatically detects and creates folder from arbitrary filename on system slashes)
ps previous answer is awesome
/**
* create file with content, and create folder structure if doesn't exist
* #param String $filepath
* #param String $message
*/
function forceFilePutContents ($filepath, $message){
try {
$isInFolder = preg_match("/^(.*)\/([^\/]+)$/", $filepath, $filepathMatches);
if($isInFolder) {
$folderName = $filepathMatches[1];
$fileName = $filepathMatches[2];
if (!is_dir($folderName)) {
mkdir($folderName, 0777, true);
}
}
file_put_contents($filepath, $message);
} catch (Exception $e) {
echo "ERR: error writing '$message' to '$filepath', ". $e->getMessage();
}
}
i have Been Working on the laravel Project With the Crud Generator and this Method is not Working
#aqm so i have created my own function
PHP Way
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!file_exists($directoryPathOnly))
{
mkdir($directoryPathOnly,0775,true);
}
file_put_contents($fullPathWithFileName, $fileContents);
}
LARAVEL WAY
Don't forget to add at top of the file
use Illuminate\Support\Facades\File;
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!File::exists($directoryPathOnly))
{
File::makeDirectory($directoryPathOnly,0775,true,false);
}
File::put($fullPathWithFileName,$fileContents);
}
I created an simpler answer from #Manojkiran.A and #Savageman. This function can be used as drop-in replacement for file_put_contents. It doesn't support context parameter but I think should be enough for most cases. I hope this helps some people. Happy coding! :)
function force_file_put_contents (string $pathWithFileName, mixed $data, int $flags = 0) {
$dirPathOnly = dirname($pathWithFileName);
if (!file_exists($dirPathOnly)) {
mkdir($dirPathOnly, 0775, true); // folder permission 0775
}
file_put_contents($pathWithFileName, $data, $flags);
}
Easy Laravel solution:
use Illuminate\Support\Facades\File;
// If the directory does not exist, it will be create
// Works recursively, with unlimited number of subdirectories
File::ensureDirectoryExists('my/super/directory');
// Write file content
File::put('my/super/directory/my-file.txt', 'this is file content');
I wrote a function you might like. It is called forceDir(). It basicaly checks whether the dir you want exists. If so, it does nothing. If not, it will create the directory. A reason to use this function, instead of just mkdir, is that this function can create nexted folders as well.. For example ('upload/promotions/januari/firstHalfOfTheMonth'). Just add the path to the desired dir_path.
function forceDir($dir){
if(!is_dir($dir)){
$dir_p = explode('/',$dir);
for($a = 1 ; $a <= count($dir_p) ; $a++){
#mkdir(implode('/',array_slice($dir_p,0,$a)));
}
}
}
I am using Zend Framework 1.9.6. I think I've got it pretty much figured out except for the end. This is what I have so far:
Form:
<?php
class Default_Form_UploadFile extends Zend_Form
{
public function init()
{
$this->setAttrib('enctype', 'multipart/form-data');
$this->setMethod('post');
$description = new Zend_Form_Element_Text('description');
$description->setLabel('Description')
->setRequired(true)
->addValidator('NotEmpty');
$this->addElement($description);
$file = new Zend_Form_Element_File('file');
$file->setLabel('File to upload:')
->setRequired(true)
->addValidator('NotEmpty')
->addValidator('Count', false, 1);
$this->addElement($file);
$this->addElement('submit', 'submit', array(
'label' => 'Upload',
'ignore' => true
));
}
}
Controller:
public function uploadfileAction()
{
$form = new Default_Form_UploadFile();
$form->setAction($this->view->url());
$request = $this->getRequest();
if (!$request->isPost()) {
$this->view->form = $form;
return;
}
if (!$form->isValid($request->getPost())) {
$this->view->form = $form;
return;
}
try {
$form->file->receive();
//upload complete!
//...what now?
$location = $form->file->getFileName();
var_dump($form->file->getFileInfo());
} catch (Exception $exception) {
//error uploading file
$this->view->form = $form;
}
}
Now what do I do with the file? It has been uploaded to my /tmp directory by default. Obviously that's not where I want to keep it. I want users of my application to be able to download it. So, I'm thinking that means I need to move the uploaded file to the public directory of my application and store the file name in the database so I can display it as a url.
Or set this as the upload directory in the first place (though I was running into errors while trying to do that earlier).
Have you worked with uploaded files before? What is the next step I should take?
Solution:
I decided to put the uploaded files into data/uploads (which is a sym link to a directory outside of my application, in order to make it accessible to all versions of my application).
# /public/index.php
# Define path to uploads directory
defined('APPLICATION_UPLOADS_DIR')
|| define('APPLICATION_UPLOADS_DIR', realpath(dirname(__FILE__) . '/../data/uploads'));
# /application/forms/UploadFile.php
# Set the file destination on the element in the form
$file = new Zend_Form_Element_File('file');
$file->setDestination(APPLICATION_UPLOADS_DIR);
# /application/controllers/MyController.php
# After the form has been validated...
# Rename the file to something unique so it cannot be overwritten with a file of the same name
$originalFilename = pathinfo($form->file->getFileName());
$newFilename = 'file-' . uniqid() . '.' . $originalFilename['extension'];
$form->file->addFilter('Rename', $newFilename);
try {
$form->file->receive();
//upload complete!
# Save a display filename (the original) and the actual filename, so it can be retrieved later
$file = new Default_Model_File();
$file->setDisplayFilename($originalFilename['basename'])
->setActualFilename($newFilename)
->setMimeType($form->file->getMimeType())
->setDescription($form->description->getValue());
$file->save();
} catch (Exception $e) {
//error
}
By default, files are uploaded to the system temporary directory, which means you'll to either :
use move_uploaded_file to move the files somewhere else,
or configure the directory to which Zend Framework should move the files ; your form element should have a setDestination method that can be used for that.
For the second point, there is an example in the manual :
$element = new Zend_Form_Element_File('foo');
$element->setLabel('Upload an image:')
->setDestination('/var/www/upload')
->setValueDisabled(true);
(But read that page : there are other usefull informations)
If you were to move the file to a public directory, anyone would be able to send a link to that file to anyone else and you have no control over who has access to the file.
Instead, you could store the file in the DB as a longblob and then use the Zend Framework to provide users access the file through a controller/action. This would let you wrap your own authentication and user permission logic around access to the files.
You'll need to get the file from the /tmp directory in order to save it to the db:
// I think you get the file name and path like this:
$data = $form->getValues(); // this makes it so you don't have to call receive()
$fileName = $data->file->tmp_name; // includes path
$file = file_get_contents($fileName);
// now save it to the database. you can get the mime type and other
// data about the file from $data->file. Debug or dump $data to see
// what else is in there
Your action in the controller for viewing would have your authorization logic and then load the row from the db:
// is user allowed to continue?
if (!AuthenticationUtil::isAllowed()) {
$this->_redirect("/error");
}
// load from db
$fileRow = FileUtil::getFileFromDb($id); // don't know what your db implementation is
$this->view->fileName = $fileRow->name;
$this->view->fileNameSuffix = $fileRow->suffix;
$this->view->fileMimeType = $fileRow->mime_type;
$this->view->file = $fileRow->file;
Then in the view:
<?php
header("Content-Disposition: attachment; filename=".$this->fileName.".".$this->fileNameSuffix);
header('Content-type: ".$this->fileMimeType."');
echo $this->file;
?>
$this->setAction('/example/upload')->setEnctype('multipart/form-data');
$photo = new Zend_Form_Element_File('photo');
$photo->setLabel('Photo:')->setDestination(APPLICATION_PATH ."/../public/tmp/upload");
$this->addElement($photo);