action download in gridview yii2 - yii2

I'm very new with YII2. I want to create a download function to the file that was uploaded before. I've referred how to create action download at Gridview in Yii2. However, when I click button download, it load the blank page. Here the code.
At gridview
<?=GridView::widget([
'dataProvider'=>$dataProvider,
'id'=>'mygrid',
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'project_name',
'project_file',
'created_date',
[
'class' => 'yii\grid\ActionColumn',
],
['attribute'=>'Download',
'format'=>'raw',
'value' => function($data)
{
return
Html::a('Download file', ['firstyear/download', 'id' => $data->id],['class' => 'btn btn-primary']);
}
],
]
]);
?>
At actionDownload
public function actionDownload($id)
{
$download = Firstyear::findOne($id);
$path=Yii::getAlias('#webroot').'/uploads/'.$download->project_file;
if (file_exists($path)) {
return Yii::$app->response->sendFile($path);
}
}
At actionCreate (upload file)
public function actionCreate()
{
$model = new Firstyear();
if ($model->load(Yii::$app->request->post()))
{
$project =$model->project_name;
$model->file= UploadedFile::getInstance($model,'file');
$model-> file->saveAs('uploads/'.$project.'.'.$model->file->extension);
$model->project_file='uploads/'.$project.'.'.$model->file->extension;
$model->save();
Yii::$app->getSession()->setFlash('success','Data saved!');
return $this->redirect(['view','id'=> $model->id]);
}
else {
return $this ->renderAjax('create', [
'model'=>$model,
]);
}
}
Thanks.

I suspect that the $path is not correct, in the action create, you already include the uploads folder in your $model->project_file
public function actionCreate()
{
$model = new Firstyear();
if ($model->load(Yii::$app->request->post()))
{
.......
$model->project_file='uploads/'.$project.'.'.$model->file->extension;
$model->save();
....
}
}
but you use it again in actionDownlaod
public function actionDownload($id)
{
.....
$path=Yii::getAlias('#webroot').'/uploads/'.$download->project_file;
if (file_exists($path)) {
return Yii::$app->response->sendFile($path);
}
}
you should try to remove the uploads folder in the actionDownlaod, and added some debug message
public function actionDownload($id)
{
.....
$path=Yii::getAlias('#webroot').'/'.$download->project_file;
if (file_exists($path)) {
return Yii::$app->response->sendFile($path);
} else {
throw new NotFoundHttpException("can't find {$download->project_file} file");
}
}

Related

How to set home page in Yii2

public function actionIndex() {
$this->layout = 'landing';
$loginForm = new LoginForm();
if (\Yii::$app->request->getIsPost()) {
$loginForm->load(\Yii::$app->request->post());
if ($loginForm->validate()) {
$user = $loginForm->getUser();
\Yii::$app->user->login($user);
return $this->goHome();
}
}
}
method goHome() sends to the home page. I have added '' => 'site/index' to the URL Manager earlier to send people to the SiteController and Index action, but Yii2 does not do anything. How to set up a correct home page rule?
You should write homeUrl parameter on config/main.php. For example:
return [
'id' => 'app-frontend',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'homeUrl' => ['some/home-url-example'],
'modules' => [
...
],
...
]

captcha not working using scenarios in yii2

I am trying to add captcha validation based on scenario, for which I am first retrieving number of failed attempts from database. For which I am using checkattempts() function. Based on the result I am displaying captcha in view and adding scenario condition in controller as below.
In LoginForm model:
public function rules()
{
return [
[['username', 'password'], 'required', 'on'=>'loginpage'],
[['username', 'password'], 'required', 'on'=>'withCaptcha'],
[['reference_url'], 'safe'],
[['verifyCode'], 'captcha', 'skipOnEmpty' => true,'on'=>'withCaptcha'],
['username','email', 'on'=>'loginpage', 'message'=> 'Please enter a valid email address'],
['password', 'validatePassword', 'on'=>'loginpage'],
['password', 'validatePassword', 'on'=>'withCaptcha'],
];
}
public function checkattempts($uname)
{
$user = \frontend\models\User::findByEmail($uname);
$ip = $this->get_client_ip();
if($user){
$data = (new Query())->select('*')
->from('login_attempts')
->where(['ip' => $ip])->andWhere(['user_ref_id' => $user->id])
->one();
if($data["attempts"] >=3){
return true;
}else{
return false;
}
}
return false;
}
in SiteController.php controller
public function actionLogin() {
if (!\Yii::$app->user->isGuest) {
return $this->redirect(Yii::$app->getUrlManager()->getBaseUrl() . '/../../');
}
$model = new \common\models\LoginForm();
$model->scenario = 'loginpage';
$captcha = false;
if(Yii::$app->request->post()){
$post_variables =Yii::$app->request->post('LoginForm');
if ($model->checkattempts($post_variables['username'])) {
$model->scenario = 'withCaptcha';
$captcha = true;
}
}
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$model->login(); print_r($model->getErrors()); exit;
} else {
return $this->render('login', [
'model' => $model, 'captcha' => $captcha,
]);
}
In my login.php view:
<?php if($captcha) { ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(),
['template' => '<div class="captcha_img">{image}</div>'
. '<a class="refreshcaptcha" href="#">'
. Html::img('/images/imageName.png',[]).'</a>'
. 'Verification Code{input}',
])->label(FALSE); ?>
<?php } ?>
In my controller when I am tring to print model errors at $model->login() function it is giving below error everytime even though the verification code is correct.
Array ( [verifycode] => Array ( [0] => The verification code is incorrect. ) )
Why is it failing every time. Is there any mistake in the code written?
Thanks in advance

Yii2 upload multiple success but save only first value to database

I'm coding a multiple upload function for my website. The upload was successful. But it's only save the first value to my database. Example i upload 3 files name 1.jpg, 2.jpg, 3.jpg. Then it will upload the 3 files successfully but save only the 1.jpg's name to database.
My controllers
public function actionCreate()
{
$model = new Resource3d();
if ($model->load(Yii::$app->request->post())) {
$model->files = UploadedFile::getInstances($model, 'files');
foreach ($model->files as $files){
$files->saveAs('uploads/resource3d/' . $files->baseName . $files->extension);
$model->path = '../web/uploads/resource3d/'. $files->baseName . $files->extension;
$model->name = $files->baseName;
$model->save();
}
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
My models:
public $files;
public function rules()
{
return [
[['name', 'path'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'maxFiles' => 0],
];
}
Please help.
Thank you.
You are creating single object of your model Resource3d. You need to create multiple object if you want to save multiple records.
Try this :
public function actionCreate()
{
$model = new Resource3d();
if ($model->load(Yii::$app->request->post())) {
$model->files = UploadedFile::getInstances($model, 'files');
foreach ($model->files as $files){
$res_model = new Resource3d();
$res_model->load(Yii::$app->request->post());
$files->saveAs('uploads/resource3d/' . $files->baseName . $files->extension);
$res_model->path = '../web/uploads/resource3d/'. $files->baseName . $files->extension;
$res_model->name = $files->baseName;
$res_model->save();
}
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
This is just an example, change it according to your need.

Yii2 hiddenInput does not react on options value

Going to change image field in model by changing value in hidden field:
View:
<?= HTML::activeHiddenInput($model, 'image_clean', [
'id' => 'cleaner',
'name' => 'cleaner',
'value' => false
])
?>
<?=
Html::button('Remove logo', [
'id' => 'btn_clean',
])
?>
at the end of view:
<?php
$this->registerJs(<<<JS
$('#btn_clean').on('click', function() {
alert('Going to remove logo'); // Reachable!
$('#cleaner').val(true);
});
JS
);
?>
Model:
public $image_clean; // Remove logo
public function rules() {
return [
//...
[['image_clean'], 'boolean'],
//...
];
}
public function attributeLabels() {
return [
//...
'image_clean' => 'Remove logo',
//...
];
}
public function beforeValidate() {
if($this->image_clean) { } // Never!
return parent::beforeValidate();
}
public function beforeSave($insert) {
if($this->image_clean) { } // Never!
return parent::beforeSave($insert);
}
Unfortunately, $this->image_clean in model's beforeValidate / beforeSave always false. Why?
Javascript btn_clean handler works as it should be.
Hiddeninput's name overrides default one.
So, I just remove 'name' => 'cleaner'. It's not required

yii2 is not getting id in action after $model->save() and when I click the update item icon

I have a yii2 project, I am developing on my windows localhost and hosting remotely on linux.
Locally (windows) every thing is perfect.
While on linux, I have $model->id = null after $nodel->save(), although data is saved.
public function actionCreate() {
$model = new AppBreakingNews();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
I have tried die($model->id) after the save, it printed null.
Moreover, when I click on the update icon in the grid view, I am facing the same problem.
The AppBreakingNews is as follows:
<?php
namespace app\models\appmodels;
use app\models\BreakingNews;
use yii\behaviors\TimestampBehavior;
class AppBreakingNews extends BreakingNews {
public function behaviors() {
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => date('Y-m-d H:i:s'),
],
];
}
}
Notice that appBreakingNews extends the model BreakingNews that is generated by yii2 without any change.
Thanks in advance..
Please try to save model->save(false); because i think it validate something from model file.
public function actionCreate() {
$model = new AppBreakingNews();
if ($model->load(Yii::$app->request->post()) && $model->save(false)) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
or can you please print your model file here.