kartik-v / yii2-widget-fileinput

An enhanced FileInput widget for Bootstrap 4.x/3.x with file preview, multiple selection, and more features (sub repo split from yii2-widgets)
Other
229 stars 96 forks source link

Preview multiple loaded files #161

Closed mondomeme closed 4 years ago

mondomeme commented 4 years ago

Related Issue I'm trying to use kartik fileinput for loading multiple files in my form.

I use my Attachment table to save in the db the filename and other fields and I save the files in my filesystem. I usually link the Attachment with Registry table via RegistryAttachment table.

If I have already load files for a particular Registry, I want to display them in the widget.

I searched a solution and I find kartik file input preview demo which shows how configure the widget for loaded multiple files preview. So I have modified my code as following:

Controller action

public function actionLoadMultiple($registryId = NULL){

    $model = new Attachment();

    if(!$registryId){
        $model->files = [];
        $registryId = 5;//For example
        $registry = \app\models\Registry::findOne($registryId);
        $registryAttachments = $registry->attachments;//Find all Attachment record for registryId
        foreach($registryAttachments as $attachment){
             //I set the file path 
            $model->files[$attachment->original_filename]['filePath'] = $attachment->filePath();
           //I have to insert the url file for the preview
            $model->files[$attachment->original_filename]['viewPath'] = 
                    'http://general.finamar.eu/test_attachments/reg/'.$attachment->filename;

        }
    }
    if (Yii::$app->request->isPost) {
        //Carichiamo nel model i file dal form.
        //una volta caricati vengono salvati invocando la funzione uplodMultiple dal model

        $oldFiles = [];
        if($model->files){
            $oldFiles = $model->files;
        }
        $model->files = UploadedFile::getInstances($model, 'files');
        $loadedFiles = $model->uploadMultiple();
        if ($loadedFiles) {
            // file is uploaded successfully
            foreach($loadedFiles as $originalFileName=>$fileName){
                $attachment = new Attachment();
                $attachment->section = $model->section?: 'oth';
                $attachment->description = $model->description ?: 'Other';
                $attachment->filename = $fileName;
                $attachment->original_filename =$originalFileName;
                if(!$attachment->save()){
                    $attachment->removeFile();//cancello il file
                    return ['error'=>\Yii::t('app','Error saving attachments to db. Please contact an administrator')];
                }
                if(isset($registryId)){
                    $regAtt = new \app\models\RegistryAttachment();
                    $regAtt->registry_id = $registryId;
                    $regAtt->attachment_id = $attachment->attachment_id;
                    if(!$regAtt->save()){
                        $attachment->removeFile();
                        return false;
                    }
                }
            }
            return $this->redirect(['index']);
        }
    }

    return $this->render('load_multiple',['model'=>$model]);
}

Model functions

   **Model function**

public function uploadMultiple(){
    $files = $this->files;
    $section = $this->section ?: '';
    if(!$files){
        return false;
    }

    $fileNameList = [];
    $path = Utility::getAttachmentsBasePath();
    $count = 1;
    foreach ($files as $file) {
        if (!$section) {
            $section = 'oth';
        }

        $filename = \app\models\Attachment::generateFilename($file->name);

        //I set the path to the right folder
        $completePath = $path . '/' . $section . '/' . $filename;
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            $completePath = str_replace('/', '\\', ($completePath));
        }

        if (!$file->saveAs($completePath)) {
            Yii::error("Error loading file - error code {$file->error}", "upload");
            return ['error' => \Yii::t('app', 'Error saving files. Please contact an administrator')];
        }

        if (isset($fileNameList[$file->name])) {
            $fileNameList[$file->name . '_' . $count] = $filename ;
            $count++;
        } else {
            $fileNameList[$file->name] = $filename;
        }
    }
    return $fileNameList;
}
  public function filePath(){
    $basePath = Yii::$app->params['attachmentsBasePath'];
    $completePath = $basePath .'/'.$this->section.'/'.$this->filename;
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        $completePath = str_replace('/', '\\', ($completePath));
    }
    return $completePath;
}

public static function fileInputTypeForUploaded($filename){
     $estens = substr($filename, strrpos($filename, '.') );

     switch ($estens){
        case  '.txt' :
            return 'text';

        case '.doc' :
        case '.docx' :   
        case '.ppt' :
        case '.pptx' :   
        case '.xls':
        case '.xlsx' :
            return 'office';

        case '.pdf': 
            return 'pdf';

        case '.jpg':
        case '.jpeg':
        case '.png':
        case '.gif':
        case '.tif':
        case '.tiff':
            return 'image';    

        case '.wav':
        case '.mp3':
        case '.m4a':
        case '.ogg':
        case '.flac': 
        case '.wma':
        case '.aac':
        case '.gsm':
        case '.dct':  
        case '.aiff':
        case '.au':    
            return 'audio';   

        default:
            return 'other';    

     }

View load-multiple

<?php

    use yii\widgets\ActiveForm;
    use kartik\file\FileInput;
    use yii\helpers\Html;

    $this->title = Yii::t('app', 'Create Multiple Attachment');
    $initialPreviewAttachmentFile = [];
    $initialPreviewAttachmentCaption = [];
    $fileInputShowRemove = true;
    $rootTagClassName = 'attachment-create';

    if($model->files){
       foreach($model->files as $key=>$file){
       $type = \app\models\Attachment::fileInputTypeForUploaded($key);
       $initialPreviewFile = $file['viewPath'];
       if($type == 'text'){
         $initialPreviewFile = file_get_contents($file['filePath']);
       }
       $initialPreviewAttachmentFile[] =  $initialPreviewFile;
       $initialPreviewAttachmentCaption[] = [
        'caption'=>$key,
        'type'=>$type,
        'size'=> filesize($file['filePath']),
    ];
}
}

  $form = ActiveForm::begin(['enableAjaxValidation' => true,]);

  echo $form->field($model, 'files[]')->widget(FileInput::class, 
    [
        'name' => 'files[]',
        'options' => ['multiple' => true],
        'pluginOptions' => [
            'minFileCount' => 0,
            'maxFileCount' => 10,
            'maxFileSize' => Yii::$app->params["attachmentsMaxSize"],
            'initialPreview' => $initialPreviewAttachmentFile ,
            'initialPreviewAsData' => true,
            'initialPreviewConfig' => $initialPreviewAttachmentCaption,
            'fileActionSettings' => [
                'showDownload' => false,
                'showRemove' => true,
            ],
            'uploadUrl' => '',
            'showUpload' => false,
            'defaultPreviewContent' => yii\helpers\Url::to(["/common-files/images/empty-file.png"]),
            'overwriteInitial'=>false,
            'showRemove' => TRUE,
        ],
    ]);
 ?>

This is the result: result.

However, now I have new problems:

  1. If I want to remove a loaded file from the preview, I click on the remove file button, but it does nothing.
  2. If I load a new file, in the thumb file preview there isn't the remove button, as shown in the following image: remove not showed 3.I want to submit all files, included the already saved ones. Is there a way to do it?
mondomeme commented 4 years ago

I have solved checking on documentation