Blackjack
Blackjack

Reputation: 1065

Yii2: Kartik InputFile show "Single File Upload Failed" error message in progress bar

I have a application using Yii2 basic framework, and I'm using Kartik InputFile for upload file. The file successfully uploaded to the system, and the page also successfully redirect to next page, but a few second before the page redirect to next page, it display an error in progress bar like this enter image description here

Why this widget show notification "upload failed" although the file successfully uploaded?

This is my code in _form.php:

<?php $form = ActiveForm::begin(); ?>
<?php
echo FileInput::widget([
    'name' => 'file_uploads',
    'language' => 'id',
    'options' => [
        'accept' => 'doc/*', 'file/*',
        'multiple' => true,
        'enableLabel' => true,
    ],
    'pluginOptions' => [
        'allowedFileExtensions' => ['xls', 'xlsx'],
        'uploadUrl' => Url::to(['/pib/pib-data/create']),
        'maxFileSize' => 1024,
        'maxFileCount' => 1,
        'showCaption' => false,
        'showMessage'=>false,
        'purifyHtml'=>false
    ]
]);
?>
<?php ActiveForm::end(); ?>

and this the code that I've used in controller:

<?php
public function actionCreate() {
    $model = new PibData();
    $connection = \Yii::$app->db;
    $userId = Yii::$app->user->id;
    if (Yii::$app->user->isGuest) {
        return $this->redirect(['/site/login']);
    }

    $sqlHeader = "UPDATE pib_data SET is_exported = '1' WHERE user_id = '$userId'";
    $exeQuery = Yii::$app->db->createCommand($sqlHeader)->execute();
    $date = new DateTime('now', new \DateTimeZone('Asia/Jakarta'));
    $created_at = $date->format('Y:m:d H:i:s');
    $dirTrash = Yii::getAlias('@webroot/trash');
    $dirSubTrash = Yii::getAlias('@webroot/trash/trash_pib');

    if (!is_dir($dirTrash)) {
        mkdir(Yii::getAlias('@webroot/trash'));
        if (!is_dir($dirSubTrash)) {
            mkdir(Yii::getAlias('@webroot/trash/trash_pib'));
        }
    } else {
        if (!is_dir($dirSubTrash)) {
            mkdir(Yii::getAlias('@webroot/trash/trash_pib'));
        }
    }

    if (Yii::$app->request->post()) {
        $file = UploadedFile::getInstancesByName('file_uploads');
        $middleName = substr(md5(microtime() * 100000), rand(0, 9), 5);
        if ($file !== null) {
            $name = $userId . '_' . $middleName . '_' . date('Y-m-d') . '_' . $file[0]->getBaseName() . "." . $file[0]->getExtension();
            $pathproduct = Yii::getAlias('@webroot/trash/trash_pib/') . $name;
            $file[0]->saveAs($pathproduct);
        Yii::$app->response->format = Response::FORMAT_JSON;
        return [];
        } else {
            $error[] = "Silahkan pilih terlebih dahulu file" . "<strong>" . " Excel " . "</strong>" . "yang akan di convert.";
            Yii::$app->session->setFlash('error', $error);
            return $this->render('create', ['model' => $model]);
        }

        $modelUser = Users::find()->where(['id' => $userId])->one();
        $parentId = $modelUser->parent_id;

        $objPHPExcel = new \PHPExcel();
        $fileName = Yii::getAlias('@webroot/trash/trash_pib/') . $name;
        $inputFiles = fopen(Yii::getAlias('@webroot/trash/trash_pib/') . $name, "r");
        try {
            $inputFileType = \PHPExcel_IOFactory::identify($fileName);
            $objReader = \PHPExcel_IOFactory::createReader($inputFileType);
            $objPHPExcel = $objReader->load($fileName);
        } catch (Exception $ex) {
            die('Error');
        }

        $sheet = $objPHPExcel->getSheet(0);
        $highestRow = $sheet->getHighestDataRow();
        $highestColumn = $sheet->getHighestDataColumn();
        $colNumber = PHPExcel_Cell::columnIndexFromString($highestColumn);
        $col = $colNumber - 1;
        $arrayData = [];
        
        for ($row = 1; $row <= $highestRow; ++$row) {
            $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE);
            $arrayData[] = array_map(function($values) {
                $tempArray = [];
                foreach ($values as $key => $value) {
                    $newKey = $key + 1;
                    $tempArray[] = $newKey . '_' . $value;
                }
                return $tempArray;
            }, $rowData);
        }

        $arrayHeader = array_shift($arrayData);
        $countArrayData = count($arrayData);
        $countArrayHeader = count($arrayHeader[0]);

        for ($i = 0; $i < $countArrayData; $i++) {
            for ($j = 0; $j < $countArrayHeader; $j++) {
                if ($j < 9) {
                    $finalData[$i][] = substr($arrayData[$i][0][$j], 2);
                } else {
                    $finalData[$i][] = substr($arrayData[$i][0][$j], 3);
                }
            }
        }

        for ($x = 0; $x < $countArrayData; $x++) {
            array_unshift($finalData[$x], "dummy");
        }

        $tempData = mysql_escape_string(json_encode($finalData));
        $tempHeader = json_encode($arrayHeader);
        $header = base64_encode($tempHeader);

        $command_1 = "DELETE FROM pib_json_data WHERE user_id= '$userId'";
        $query_1 = Yii::$app->db->createCommand($command_1)->execute();
        $command_2 = "INSERT INTO pib_json_data(json_data, user_id, created_at) VALUES('$tempData', '$userId', '$created_at')";
        $query_2 = Yii::$app->db->createCommand($command_2)->execute();

        $_SESSION['header'] = $header;
        $_SESSION['validHeader'] = 'validHeader';

        return Yii::$app->response->redirect(['/pib/pib-header/select-header']);
    } else {
        return $this->render('create', [
                    'model' => $model,
        ]);
    }
}
?>

anyhelp will be apreciated.

Thanks

Upvotes: 0

Views: 1508

Answers (1)

MegaGrindStone
MegaGrindStone

Reputation: 89

Well... according to documentation, in "IMPORTANT" section:

You MUST send a valid JSON response from your server, else the upload process will fail. Even if you do not encounter any error, you must at least send an empty JSON object {} from your server.

So, i believe your code should look like this.

Controller :

<?php
public function actionCreate() {
    $model = new PibData();
    $connection = \Yii::$app->db;
    $userId = Yii::$app->user->id;
    if (Yii::$app->user->isGuest) {
        return $this->redirect(['/site/login']);
    }

    $sqlHeader = "UPDATE pib_data SET is_exported = '1' WHERE user_id = '$userId'";
    $exeQuery = Yii::$app->db->createCommand($sqlHeader)->execute();
    $date = new DateTime('now', new \DateTimeZone('Asia/Jakarta'));
    $created_at = $date->format('Y:m:d H:i:s');
    $dirTrash = Yii::getAlias('@webroot/trash');
    $dirSubTrash = Yii::getAlias('@webroot/trash/trash_pib');

    if (!is_dir($dirTrash)) {
        mkdir(Yii::getAlias('@webroot/trash'));
        if (!is_dir($dirSubTrash)) {
            mkdir(Yii::getAlias('@webroot/trash/trash_pib'));
        }
    } else {
        if (!is_dir($dirSubTrash)) {
            mkdir(Yii::getAlias('@webroot/trash/trash_pib'));
        }
    }

    if (Yii::$app->request->post()) {
        Yii::$app->response->format = Response::FORMAT_JSON;
        $result = [];
        $file = UploadedFile::getInstancesByName('file_uploads');
        $middleName = substr(md5(microtime() * 100000), rand(0, 9), 5);
        if ($file !== null) {
            $name = $userId . '_' . $middleName . '_' . date('Y-m-d') . '_' . $file[0]->getBaseName() . "." . $file[0]->getExtension();
            $pathproduct = Yii::getAlias('@webroot/trash/trash_pib/') . $name;
            $file[0]->saveAs($pathproduct);
        } else {
            $error[] = "Silahkan pilih terlebih dahulu file" . "<strong>" . " Excel " . "</strong>" . "yang akan di convert.";
            //Yii::$app->session->setFlash('error', $error);
            //return $this->render('create', ['model' => $model]);
            $result = [
                'error' => $error
            ]; // change error notification used Kartik FileInput build-in error message 
        }

        $modelUser = Users::find()->where(['id' => $userId])->one();
        $parentId = $modelUser->parent_id;

        $objPHPExcel = new \PHPExcel();
        $fileName = Yii::getAlias('@webroot/trash/trash_pib/') . $name;
        $inputFiles = fopen(Yii::getAlias('@webroot/trash/trash_pib/') . $name, "r");
        try {
            $inputFileType = \PHPExcel_IOFactory::identify($fileName);
            $objReader = \PHPExcel_IOFactory::createReader($inputFileType);
            $objPHPExcel = $objReader->load($fileName);
        } catch (Exception $ex) {
            //die('Error');
            $result = [
                'error' => $ex
            ]; // change error notification used Kartik FileInput build-in error message 
        }

        $sheet = $objPHPExcel->getSheet(0);
        $highestRow = $sheet->getHighestDataRow();
        $highestColumn = $sheet->getHighestDataColumn();
        $colNumber = PHPExcel_Cell::columnIndexFromString($highestColumn);
        $col = $colNumber - 1;
        $arrayData = [];

        for ($row = 1; $row <= $highestRow; ++$row) {
            $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE);
            $arrayData[] = array_map(function($values) {
                $tempArray = [];
                foreach ($values as $key => $value) {
                    $newKey = $key + 1;
                    $tempArray[] = $newKey . '_' . $value;
                }
                return $tempArray;
            }, $rowData);
        }

        $arrayHeader = array_shift($arrayData);
        $countArrayData = count($arrayData);
        $countArrayHeader = count($arrayHeader[0]);

        for ($i = 0; $i < $countArrayData; $i++) {
            for ($j = 0; $j < $countArrayHeader; $j++) {
                if ($j < 9) {
                    $finalData[$i][] = substr($arrayData[$i][0][$j], 2);
                } else {
                    $finalData[$i][] = substr($arrayData[$i][0][$j], 3);
                }
            }
        }

        for ($x = 0; $x < $countArrayData; $x++) {
            array_unshift($finalData[$x], "dummy");
        }

        $tempData = mysql_escape_string(json_encode($finalData));
        $tempHeader = json_encode($arrayHeader);
        $header = base64_encode($tempHeader);

        $command_1 = "DELETE FROM pib_json_data WHERE user_id= '$userId'";
        $query_1 = Yii::$app->db->createCommand($command_1)->execute();
        $command_2 = "INSERT INTO pib_json_data(json_data, user_id, created_at) VALUES('$tempData', '$userId', '$created_at')";
        $query_2 = Yii::$app->db->createCommand($command_2)->execute();

        $_SESSION['header'] = $header;
        $_SESSION['validHeader'] = 'validHeader';

        //return Yii::$app->response->redirect(['/pib/pib-header/select-header']);
        $result = [
            'url' => Url::to(['/pib/pib-header/select-header'])
        ]; // return url variable to be used by jquery
        return $result;
    } else {
        return $this->render('create', [
                    'model' => $model,
        ]);
    }
}
?>

View :

<?php

use yii\web\View;
...

<?php $form = ActiveForm::begin(); ?>
<?php
echo FileInput::widget([
    'name' => 'file_uploads',
    'language' => 'id',
    'options' => [
        'accept' => 'doc/*', 'file/*',
        'multiple' => true,
        'enableLabel' => true,
    ],
    'pluginOptions' => [
        'allowedFileExtensions' => ['xls', 'xlsx'],
        'uploadUrl' => Url::to(['/pib/pib-data/create']),
        'maxFileSize' => 1024,
        'maxFileCount' => 1,
        'showCaption' => false,
        'showMessage'=>false,
        'purifyHtml'=>false
    ]
]);
?>
<?php ActiveForm::end(); ?>

<?php
$this->registerJS("
    $('#input-id').on('fileuploaded', function(event, data, previewId, index) { // replace input-id with your file input id
        var response = data.response;
        $(location).attr('href', response.url); // redirect use jquery
    });", View::POS_END);

Hope it's help.

Happy coding. :)

Upvotes: 1

Related Questions