how to solve File upload validation problem in yii2 - yii2

I'm trying to upload a file in yii2, the same code was working fine before but for some reason i can't figure out it stopped working after a lot of checks i notice the validate method of upload model is returning false and in the error message it says Array ( [file] => Array ( [0] => Only files with these extensions are allowed: png, jpg,jpeg,gif,pdf. ) ) but the most weird thing is i uploaded a jpg file i also try to upload a png file the same error, when i remove the check for extension in the model rules it works fineor totally remove the validation is also work, i don't know what am missing here any help would be appreciated.
NOTE //with the validation or the extension check for extension in place the codes in the if()
statement fails to execute but rather the else statement execute, removing the validation or the
extension check the code in if() works fine
class Upload extends Model
{
public $file;
public $randomCharacter;
public $fileDirectory;
public function rules()
{
return[
[['file'], 'file', 'skipOnEmpty' => false,'maxSize'=>1024 * 1024 * 2, 'extensions'=> ['png, jpg,jpeg,gif,pdf']],
];
}
public function upload($uploadPath=NULL)
{
if(isset($uploadPath) && $uploadPath !==NULL){
$filePath = $uploadPath;
}else{
$filePath = "#frontend/web/uploads/";
}
//generate random filename
$rand = Yii::$app->security->generateRandomString(10). '_' . time();
//assign generated file name to randomCharacter property
$this->randomCharacter = $rand;
//define the upload path;
if ($this->validate()){
$path = \Yii::getAlias($filePath);
$this->fileDirectory = $this->randomCharacter .'.'.$this->file->extension;
echo $path.$this->fileDirectory;
exit;
$this->file->saveAs($path.$this->fileDirectory );
return true;
}else{
// return false;
//with validation in place the else statement in executed
print_r($this->getErrors());
exit;
}
}
}

Remove the straight brackets of attribute "extensions"
Instead of:
[['file'], 'file', 'skipOnEmpty' => false,'maxSize'=>1024 * 1024 * 2, 'extensions'=> ['png, jpg,jpeg,gif,pdf']],
You should have this:
[['file'], 'file', 'skipOnEmpty' => false,'maxSize'=>1024 * 1024 * 2, 'extensions'=> 'png, jpg, jpeg, gif, pdf'],

Related

Upload CSV data as chunks Laravel

I created my code following following few tutorials. As my csv file has more than 300k rows I need to upload it as chunks, but unable to figure out how to do that.
Mainly followed this tutorial and several others including some laracast discussions
https://itsolutionstuff.com/post/import-and-export-csv-file-in-laravel-58example.html
My Controller import function
public function import()
{
Excel::import(new ReportImport, request()->file('file'));
return view('dashboard');
}
My ReportImport File
namespace App\Imports;
use App\Report;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class ReportImport implements ToModel, WithHeadingRow
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Report([
'district' => $row['district'],
'age' => $row['age'],
'email' => $row['email'],
'name' => $row['name'],
]);
}
}
Illuminate \ Http \ Exceptions \ PostTooLargeException
No message

CakePHP 3 - Can't return proper json when debug mode = true

I'm new to stackoverflow, and I've just started to play around with CakePHP 3.
I've run into a weird problem:
I'm sending an ajax-request (form submit) to the controller, and I expect to get a proper json-response back. It works fine when I set debug mode to false in config/app.php, but when it's set to true, I get an error-message in the browsers console, and the responsetext seem to be html. I'm calling the action with the .json extension in the url.
I've linked screenshot of the console where the first response is with debug mode set to false, and the second set to true:
I have enabled the extensions in config/routes.php:
Router::scope('/', function (RouteBuilder $routes) {
$routes->extensions(['json', 'xml']);
(...)
Here's the controller-code:
public function getUserStats() {
$this->log($this->request->data, 'debug');
if (($this->request->is('post'))) {
$this->log('getCategories(): Post-request is received.', 'info');
$usersTable = TableRegistry::get('Users');
$q = $usersTable->find('statsByUsers', $this->request->data);
$users = $q->all();
// Calculating total amount per user.
foreach ($users as $u) {
foreach ($u->purchases as $p) {
$u->total += $p->total;
}
}
$this->log($users, 'debug');
$this->set('users', $users);
$this->set('_serialize', ['users']);
}
}
Here's the model code:
public function findStatsByUsers(Query $query, array $options) {
debug($options);
$options['dates'] = $this->getConvertedDates($options);
$query
->contain([
'Purchases' => function($q) use($options) {
return $q
->select(['id', 'total' => 'amount * count', 'purchase_date', 'user_id'])
->where(['purchase_date BETWEEN :fromDate AND :toDate',])
->bind(':fromDate', $options['dates']['fromDate'], 'datetime') // Binds the dates to the variables in where-conditions
->bind(':toDate', $options['dates']['toDate'], 'datetime');
}
])
->where([
'Users.id IN ' => $options['users'],
'Users.active' => true
]);
return $query;
}
I hope I've given you enough information so that you can help me solve this.
CakePHP version: 3.3.2
Looking at the bit of output that is visible in the screenshot
<div class="cake-debug-output"> ...
that HTML is output generated by the debug() function.
Look closely at your model code, and you should spot the call to the function. Remove it, and you should be good.
btw, the source of the call can be found in the first <span> element in the <div>, so if you experience similar problems in the future make sure to check that.
<?php
use Cake\Core\Configure;
// your class ,...
public function getUserStats() {
$this->log($users, 'debug');
Configure::write('debug',false); // DISABLE
$this->set('users', $users);
$this->set('_serialize', ['users']);
}

Yii2 use runAction() within beforeAction method

I have a MainController which extends Controller. All my app's controllers extend from MainController which includes various methods and properties which need to be accessible from any Controller.
Within my MainController is beforeAction, which does several things:
Checks for redirects held in the database and performs them if the URL matches one in the DB.
Generates <head> data for each controller
Gets the language and country the user is looking at based on cookie and slug of the URL. (i.e. http://example.com/netherlands).
Will render a generic page from a template if URL matches one from the database's pages table.
It's the last that I am struggling with. In my MainController I have this:
/**
* Before action, check all $this->before_actions satisfy. If no head_data provided, try and fill in some basics
*/
public function beforeAction( $action )
{
// Run parent method first
if (!parent::beforeAction($action))
return false;
// Check redirects
$this->checkRedirects();
if( $this->checkPages() )
{
// If not error page, loop through before methods
if( $action->id !== 'error' )
{
// Loop through actions to peform and do them
foreach ( $this->before_actions as $before_method )
$this->$before_method();
}
return true;
}
}
Where $this->checkPages() contains the following:
/**
* Check for pages
*/
public function checkPages()
{
// Attempt to find page for this request
$page = Page::find()->where( [ 'permalink' => trim( str_replace( getBaseUrl() , "", getCurrentUrl() ), "/" ) ] )->one();
// If found, load it instead
if( !empty( $page ) )
return Yii::$app->runAction( "pages/show", [ 'id' => $page->id ] );
// Else, return
return true;
}
The issue I am having is that if I go to http://example.com/story, because there is no StoryController, the returns a 404 error although the action does run and the view "views/story/show" is output.
How can I prevent this?
EDIT:
To add, the log shows that it first says:
"Unable to resolve the request 'story/index'".
But then additional logs show:
"Route to run: pages/show" ... "Running action: app\controllers\PagesController::actionShow()"
..
Rendering view file: /Users/stefandunn/Documents/Local Machine Development/views/pages/show.php
So I am guessing it's the first log result causing the 404 status
Add one last route that can catch any pattern and redirect to custom action.
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
//...
'<any:.*>' => 'site/index'
],
],

Yii2: finfo_file(C:\xampp\tmp\php29C.tmp): failed to open stream: No such file or directory

Getting error finfo_file(C:\xampp\tmp\php29C.tmp): failed to open stream: No such file or directory while uploading multiple files.
tried inserting $model->save(); before saveAs() but then it upload only one file not all files, also not getting path in database for each file which is getting uploaded.
Controller:
public function actionCreate()
{
$model = new RoomTypes();
if ($model->load(Yii::$app->request->post()))
{
$imageName = $model->room_type;
$model->file = UploadedFile::getInstances($model, 'file');
foreach ($model->file as $file_instance)
{
$model->save();
$file_instance->saveAs('uploads/room_img/' . $file_instance->baseName . '.' . $file_instance->extension);
//save the path in the db column
$file_instance->$model->images = 'uploads/room_img/'.$imageName.'.'.$file_instance->extension;
return $this->redirect(['view', 'id' => $model->id]);
}
}
else
{
return $this->render('create',
[
'model' => $model,
]);
}
}
It is possible that I already have answered this here within the last update after your comments but I'll add a different answer here as it is one more different issue beside the others. This error is thrown when using $file_instance->baseName or $file_instance->extension after saving the file. saveAs() whish its content is the following :
public function saveAs($file, $deleteTempFile = true)
{
if ($this->error == UPLOAD_ERR_OK) {
if ($deleteTempFile) {
return move_uploaded_file($this->tempName, $file);
} elseif (is_uploaded_file($this->tempName)) {
return copy($this->tempName, $file);
}
}
return false;
}
has a boolean $deleteTempFile argument set to true by default. which means it will delete the temporary file after saving and you will not be able to save the uploaded file again in the same request. You can set it to false if needed by doing :
$file_instance->saveAs('...',false)
BUT it won't be a good practice in this case as you are getting 2 copies of the same file. If the file is already saved to its new path then why not deleting it from the tmp folder. Just hold that path in a variable before calling saveAs() and use it when needed like it is done in the answer linked above :
$path = 'uploads/room_img/' . $file_instance->baseName . '.' . $file_instance->extension;
$file_instance->saveAs($path);
$model->images = $path;
Other issues you need to solve are :
foreach ($model->file as $file_instance)
{
$model->save();
$model->images = $path;
}
The $model->save() here have no logic to me. You have a single instance of an object and foreach file instance stored in its attribute $model->file you are saving the hole model again and again. And I understand from the second one ($model->images = $path) that your model have an attribute images to which you can assigning a string value. but you have multiple images here where each of them has its own path and inside the loop you are overriding it each time with the next image path string. If is the case I would probably store the path to folder where I can find all those images later instead :
$model->images = 'uploads/room_img/[a_collection_id_or_wathever_unique]/'
And inside that folder I would host the related images. Or maybe I'll host all paths separated by ; or equivalent by doing this inside the loop :
$model->images .= $path . ';';
In case if images are related models represented by an ActiveRecord class then the answer linked above should fix it.

Yii2: Finding file and getting path in a directory tree

I'm trying to search for a single filename in a bunch of directories and returning its path. I thought FileHelper::findFiles() would be a helping hand but it seems it doesn't accept a filename to search for but just a particular root directory and then it returns an array of found filenames.
Anyone who knows another Yii2 helper to accomplish this?
You should simply try:
$files = yii\helpers\FileHelper::findFiles('/path', [
'only' => ['filename.ext'],
'recursive' => true,
]);
Read more here.
You can do it easy on "pure" PHP
/**
* #var $file SplFileInfo
*/
$path = '/path';
$dirIter = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dirIter, RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
if ($file->isFile() === true && $file->getFilename() === '.htaccess') {
var_dump($file->getPathname());
}
}