This is my view file and it has one form that should post a file with a text variable data of 0000000005. But for some reason the load function inside the controller does not populate these data.
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* #var $this yii\web\View */
/* #var $model backend\models\customs\UploadForm */
/* #var $form ActiveForm */
?>
<div class="vendor_file_upload_form">
<?php $form = ActiveForm::begin(
['id' => 'form-files'],
['options' => ['enctype' => 'multipart/form-data']]
); ?>
<?= $form->field($model, 'AppFile')->fileInput() ?>
<?= $form->field($model,'apid')->textInput(); ?>
<div class="form-group">
<?= Html::submitButton(Yii::t('app', 'Submit'), ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div><!-- vendor_file_upload_form -->
This is my controller
public function actionFiles($id=null)
{
$model = new UploadForm();
if ($model->load(Yii::$app->request->post()))
{
$model->AppFile = UploadedFile::getInstance($model, 'AppFile');
if ($model->upload())
{
\Yii::$app->getSession()->setFlash('success', 'File has been successfully uploaded.');
return $this->redirect(['index']);
}
else
{
\Yii::$app->getSession()->setFlash('error', 'Wrong File Format , Try proper format.');
return $this->redirect(['index']);
}
}
}
I found that for some reason Load data does not load all the posted form parameters. I have spent 3 hours and I am still unable to understand why my form data is not being transferred properly.
I checked the Payload and I found following which means my data is coming fine but load function is not loading properly.
------WebKitFormBoundaryZfszVA0IZuj02ZFT Content-Disposition: form-data; name="_csrf-backend"
UEZaLmZ4MzEWExBjLz8LSWAnHG9SGgFhaBcqbycRZWc1dGtCAD9JYg==
------WebKitFormBoundaryZfszVA0IZuj02ZFT Content-Disposition: form-data; name="UploadForm[AppFile]"
------WebKitFormBoundaryZfszVA0IZuj02ZFT Content-Disposition: form-data; name="UploadForm[AppFile]"; filename="falcon-wallpaper.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryZfszVA0IZuj02ZFT Content-Disposition: form-data; name="UploadForm[apid]"
0000000005
------WebKitFormBoundaryZfszVA0IZuj02ZFT--
EDIT:
Below is my model file,
<?php
/**
* Created by PhpStorm.
* Date: 1/8/2017
* Time: 9:52 PM
*/
namespace backend\models\customs;
use backend\models\ApplicationFiles;
use yii\base\Model;
use yii\web\UploadedFile;
/**
* UploadForm is the model behind the upload form.
*/
class UploadForm extends Model
{
/**
* #var UploadedFile
*/
public $AppFile; //files which needs to be uploaded
public $apid; //application_id
/**
* #return array the validation rules.
*/
public function rules()
{
return [
[['apid'], 'required','message'=>'No Application Id found'],
[['AppFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
//upload on the backed/uploads folder with time stamp as the file name
if ($this->validate()) {
$File_name = time() . '.' . $this->AppFile->extension;
if($this->AppFile->saveAs(\Yii::$app->basePath.'/uploads/' .$File_name ))
{
$model = new ApplicationFiles();
$model->name = $File_name;
$model->path = \Yii::$app->basePath.'/uploads/' .$File_name;
$model->application_id = $this->apid;
// $model->type =
$model->save();
}
return true;
}
else
{
return false;
}
}
}
?>
Related
I'm working on mvc framework for a website and just want to delete old image from my image folder when i' m editing a post but get this errors:
Warning: unlink(C:\xampp\htdocs\Model View Controller2/public/images/2425.jpg): No such file or directory in C:\xampp\htdocs\Model View Controller2\app\Controller\Admin\ServicesController.php on line 72
This is my controller (when I'm editing the same image old one is deleted; its what i want for different image)
<?php
namespace App\Controller\Admin;
use Core\HTML\BootstrapForm;
use \App;
class ServicesController extends AppController{
public function __construct(){
parent::__construct();
$this->loadModel('Service');
}
public function index(){
$services = $this->Service->all();
$this->render('admin.services.index', compact('services'));
}
public function edit(){
$errors = false;
$this->loadModel('Service');
if (!empty($_POST)) {
if($_FILES['img']['size'] > 1500000){
$errors = "<strong>Ce fichier est trop lourd !</strong>";
}
if(strrchr($_FILES['img']['name'], '.') !== '.jpg'){
$errors = "<strong>L'extension de ce fichier n'est pas un .jpg !</strong>";
}
if($errors != true){
$dir = '../public/images/';
print_r($dir.$_FILES['img']['name']);
unlink($dir.$_FILES['img']['name']);
move_uploaded_file($_FILES['img']['tmp_name'], $dir.$_FILES['img']['name']);
$result = $this->Service->update($_GET['id'], array(
'titre' => $_POST['titre'],
'contenu' => $_POST['contenu'],
'img' => $dir.$_FILES['img']['name']));
}
}
$service = $this->Service->find($_GET['id']);
$services = $this->Service->extract('id', 'titre', 'contenu', 'img');
$form = new BootstrapForm($service);
$this->render('admin.services.edit', compact('services', 'form', 'errors'));
}
public function delete(){
if (!empty($_POST)) {
$result = $this->Service->delete($_POST['id']);
return $this->index();
}
}
}`
this is my view form edtit.php
<center><h1>Editer la page d'accueil Services</h1></center>
<?php if($errors): ?>
<center class="alert alert-danger">
<?= $errors; ?>
</center>
<?php endif; ?>
<form class="edit" action="" method="post" enctype="multipart/form-data">
<?= $form->input('titre', 'Titre'); ?>
<?= $form->input('contenu', 'Message', array('type' => 'textarea', 'rows' => 8)); ?>
<?= $form->input('img', 'image'); ?>
<img src="<?= $servie->img; ?>">
<?= $form->file('img', 'Choisissez une image'); ?>
<button class="btn btn-primary">Sauvegarder</button>
</form>
my ServiceTable.php
<?php
namespace App\Table;
use Core\Table\Table;
class ServiceTable extends Table{
protected $table = 'services';
/**
* Récupère les derniers article
* #return array
*/
public function last(){
return $this->query("
SELECT * FROM services");
}
}
If you want to check if the image already exists with that name, to then delete it before the upload, you could do:
if(file_exists($dir.$_FILES['img']['name'])) {
unlink($dir.$_FILES['img']['name']);
}
To prevent any warnings being thrown.
When I click on the Signup button I receive the following error: Array to string conversion.
I think that the error occurs when I call fileInput() method but i don't know how to solve it.
This is the partial code of the view
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($modelUpload, 'imageFile')->fileInput() ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
While this is the code for the controller:
<?php
class SiteController extends Controller {
/**
* Signs user up.
*
* #return mixed
*/
public function actionSignup() {
$model = new SignupForm();
$modelUpload = new UploadForm();
if ($model->load(Yii::$app->request->post()) && $modelUpload->load(Yii::$app->request->post())) {
$modelUpload->imageFile = UploadedFile::getInstances($modelUpload, 'imageFile');
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user) && $modelUpload->upload()) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
'modelUpload' => $modelUpload,
]);
}
}
This is the code of the model. It's the same of the official documentation.
<?php
class UploadForm extends Model {
/**
* #var UploadedFile
*/
public $imageFile;
public function rules() {
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload() {
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
}
?>
Errors:
Instant Solution
Change your line inside the actionSignup() from below
UploadedFile::getInstances($modelUpload, 'imageFile');
to
UploadedFile::getInstance($modelUpload, 'imageFile');
Reason
It's only a single file you are uploading not multiple files so getInstances() should be getInstance()
About
getInstance : Returns an uploaded file for the given model
attribute. The file should be uploaded using
[[\yii\widgets\ActiveField::fileInput()]]
getInstances: Returns all uploaded files for the given model
attribute.
if you want to upload multiple files - having'maxFiles' > 1 in your model's FileValidator rules - change your attribute name from:
<?= $form->field($modelUpload, 'imageFile')->fileInput() ?>
to
<?= $form->field($modelUpload, 'imageFile[]')->fileInput() ?>
read this:
https://www.yiiframework.com/doc/guide/2.0/en/input-file-upload#uploading-multiple-files
I try to handle HttpExceptions in Yii2 to Display Errormessages for Webusers. I Set everything up like here: http://www.yiiframework.com/doc-2.0/guide-runtime-handling-errors.html
Controller
namespace app\controllers;
use Yii;
use yii\web\Controller;
class SiteController extends Controller
{
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
];
}
}
public function actionError()
{
$exception = Yii::$app->errorHandler->exception;
if ($exception !== null) {
return $this->render('error', ['exception' => $exception]);
}
}
When i throw an error like this:
throw new HttpException(404,"This is an error. Maybe Page not found!");
I want to Display the Text in my view File or at least the vars described in the Docs - but alle vars are proteced or private. Any ideas how to do this?
View
$exception->statusCode // works
$exception->message // proteced
Firstly, you're defining the error action twice, once as a method of your siteController, and secondly in the actions method.
Your error message can be retrieved using the '$message' variable in your view file, using $exception->message is not correct.
The Yii documentation allows for these variables in your error view file;
name
message
exception
Try this one
$connection = \Yii::$app->db;
$transaction = $connection->beginTransaction();
try {
$model->save()
$transaction->commit();
return $this->redirect(['user/view', 'id' => $model->id]);
}catch (\Exception $e) {
$transaction->rollBack();
throw new \yii\web\HttpException(500,"YOUR MESSAGE", 405);
}
Not sure if you checked view file in views\site\error.php took me while to realize myself this is used to display error pages.
<?php
/* #var $this yii\web\View */
/* #var $name string */
/* #var $message string */
/* #var $exception Exception */
use yii\helpers\Html;
$this->title = $name;
?>
<div class="site-error">
<h1><?= Html::encode($this->title) ?></h1>
<div class="alert alert-danger">
<?php /* this is message you set in `HttpException` */ ?>
<?= nl2br(Html::encode($message)) ?>
</div>
<p>
<?= Yii::t('app', 'Here is text that is displayed on all error pages') ?>
</p>
</div>
Maybe you can try add extra content and extend the exception in Yii2 error message like this.
Just create a new custom php file called ErrorMsg.php
<?php
use Yii;
use yii\web\HttpException;
class ErrorMsg extends \Exception
{
public static function customErrorMsg($error_code,$message = null, $code = 0, \Exception $previous = null,$extra_content=NULL)
{
$httpException = new HttpException($error_code,$message,$code,$previous);
Yii::$app->response->statusCode = $error_code;
$custom_err = array(
'name'=> $httpException->getName(),
'message' => $message,
'code' => $code,
'extraContent' => $content,
'status' => $error_code,
'type' => "\\utilities\\ErrorMsg"
);
return $custom_err;
}
and call the functions wherever you want. Example
return ErrorMsg::customErrorMsg(400,"Message Here",11,NULL,"Extra Content Here");
If you want to get exception message directly from the exception class (Any of it, e.g. NotFoundException), you find that Exception::$message is protected property, but it has Exception::getMessage() public method, so in your error view, just call it.
<p class="message"><?= $exception->getMessage() ?></p>
I am working with image in Laravel 5. I use folklore package of Laravel 5. it works fine for store but shows problem while updating image.
ArticleController:
$article_to_update = $article->find($id);
$uploaded_image = $request->file('image_file');
$parameter = $request->all();
if (isset($uploaded_image))
{
$ext = $uploaded_image->getClientOriginalExtension();
$newImageName = $article_to_update->id . "." . $ext;
$uploaded_image->move(
base_path() . '/public/uploads/article/', $newImageName
);
Image::make(base_path() . '/public/uploads/article/' . $newImageName, array(
'width' => 170,
'height' => 120,
))->save(base_path() . '/public/uploads/article/' . $newImageName);
$parameter = $request->all();
$parameter['image'] = $newImageName;
unset($parameter['image_file']);
$article_to_update->update($parameter);
} else
{
$article_to_update->update($parameter);
}
Session::flash('message', 'The article was successfully edited!.');
Session::flash('flash_type', 'alert-success');
return redirect('articles');
}
Edit.blade.php:
<div class="form-group">
<label><b>IMAGE</b></label>
{!! Form::file('image_file',null,array('class'=>'form-control','id'=>'file_uploader')) !!}
{!! Form::text('image',null,array('class'=>'form-control','id'=> 'file-name')) !!}
</div>
Model:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
use \App\Auth;
/**
* Class Article
* #package App
*/
class Article extends Model {
/**
* #var array
*/
protected $guarded = [];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('App\Tag');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function category()
{
return $this->belongsTo('App\Category');
}
}
problem shows when i put a image too in the field..
Column not found: 1054 Unknown column 'image_file' in 'field list'
(SQL: update `articles` set `updated_at` = 2015-08-20 07:15:14,
`image_file` = afc-logo.gif where `id` = 457)
Anyone help?
The above code was not working because in edit form, encrypt/multipart is not used for image or any file..
so I used file=true that solved my problem..
{!! Form::model($article,['method' => 'PATCH','route'=> ['articles.update',$article->id],'files' => true]) !!}
This solves the whole updating image problem...
i have an ActiveForm, and i want to add a field where the user can upload their photos.
the problem is that i don't have an attribute for the image in the users table and every
input field in 'yii' expects a model and an attribute as follows.
<?= $form->field($model, 'attribute')->input($platforms) ?>
i don't want to assign the image to any record nor i want to insert in in the database, i want it to be uploaded to a specific folder.
i have also checked the library kartik wrote, but also requires an attribute field.
Follow the official documentation
https://github.com/yiisoft/yii2/blob/master/docs/guide/input-file-upload.md
Form Model
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
/**
* UploadForm is the model behind the upload form.
*/
class UploadForm extends Model
{
/**
* #var UploadedFile|Null file attribute
*/
public $file;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
[['file'], 'file'],
];
}
}
?>
Form View
<?php
use yii\widgets\ActiveForm;
$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'file')->fileInput() ?>
<button>Submit</button>
<?php ActiveForm::end(); ?>
Controller
Now create the controller that connects form and model together:
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->file = UploadedFile::getInstance($model, 'file');
if ($model->validate()) {
$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
}
}
return $this->render('upload', ['model' => $model]);
}
}
?>
Instead of model->load(...) we are using UploadedFile::getInstance(...). [[\yii\web\UploadedFile|UploadedFile]] does not run the model validation. It only provides information about the uploaded file. Therefore, you need to run validation manually via $model->validate(). This triggers the [[yii\validators\FileValidator|FileValidator]] that expects a file:
$file instanceof UploadedFile || $file->error == UPLOAD_ERR_NO_FILE //in code framework
If validation is successful, then we're saving the file:
$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
If you're using "basic" application template then folder uploads should be created under web.
That's it. Load the page and try uploading. Uplaods should end up in basic/web/uploads.
in your view
use kartik\widgets\ActiveForm;
use kartik\widgets\FileInput;
$form = ActiveForm::begin(['options' => ['enctype'=>'multipart/form-data']]); //important
echo FileInput::widget([
'name' => 'filename',
'showUpload' => false,
'buttonOptions' => ['label' => false],
'removeOptions' => ['label' => false],
'groupOptions' => ['class' => 'input-group-lg']
]);
echo Html::submitButton('Submit', ['class'=>'btn btn-primary']);
ActiveForm::end();
in your controller
$file = \yii\web\UploadedFile::getInstanceByName('filename');
$file->saveAs('/your/directory/'.$file->name);
Create a read only attribute for your model like public $imageand proceed like
<?= $form->field($model, 'image')->fileInput() ?>
I really like Yii2 Dropzone.
Installation:
composer require --prefer-dist perminder-klair/yii2-dropzone "dev-master"
Usage:
<?php
echo \kato\DropZone::widget([
'options' => [
'url'=> Url::to(['resource-manager/upload']),
'paramName'=>'image',
'maxFilesize' => '10',
],
'clientEvents' => [
'complete' => "function(file){console.log(file)}",
'removedfile' => "function(file){alert(file.name + ' is removed')}"
],
]);
?>
Controller:
public function actionUpload(){
$model = new ResourceManager();
$uploadPath = Yii::getAlias('#root') .'/uploads/';
if (isset($_FILES['image'])) {
$file = \yii\web\UploadedFile::getInstanceByName('image');
$original_name = $file->baseName;
$newFileName = \Yii::$app->security
->generateRandomString().'.'.$file->extension;
// you can write save code here before uploading.
if ($file->saveAs($uploadPath . '/' . $newFileName)) {
$model->image = $newFileName;
$model->original_name = $original_name;
if($model->save(false)){
echo \yii\helpers\Json::encode($file);
}
else{
echo \yii\helpers\Json::encode($model->getErrors());
}
}
}
else {
return $this->render('upload', [
'model' => $model,
]);
}
return false;
}
give this code after your uploaded code
//save the path in DB..
$model->file = 'uploads/'.$imageName.'.'.$model->file->extension;
$model->save();
If you have more than one file while uploading you must use foreach for that. And you should actual name of file in a column in table and a encrypted value of that name has to be stored to avoid duplicated in the directory.. Something like this..
$userdocs->document_name = UploadedFile::getInstances($userdocs, 'document_name');
foreach ($userdocs->document_name as $key => $file) {
$img_name = Yii::$app->security->generateRandomString();
$file->saveAs('user/business_files/' . $img_name . '.' . $file->extension);
$images = $img_name . '.' . $file->extension;
$userdocs->actual_name = $file->name;
$userdocs->user_id = $user->id;
$userdocs->document_name = $images;
$userdocs->save(false);
$userdocs = new UserDocs();
}
Here a random string is generated and it will be assign with the name of the document, and it will be stored in the table. The UserDocs is the model name.