add Image and Upload helper classes

This commit is contained in:
Roland Schneider 2015-11-29 08:28:09 +01:00
parent 40509961cd
commit ed80f8720d
10 changed files with 501 additions and 25 deletions

3
.gitignore vendored
View File

@ -32,4 +32,5 @@ phpunit.phar
/node_modules
/frontend/web/profile/**
!/frontend/web/profile/.gitkeep
!/frontend/web/profile/.gitkeep
/frontend/web/uploads/**

View File

@ -1,8 +1,11 @@
<?php
namespace backend\controllers;
use yii\rest\ActiveController;
use yii\rest\Controller;
use common\models\Image;
use backend\models\UploadForm;
use yii\web\UploadedFile;
USE Yii;
class UploadController extends Controller
{
@ -19,28 +22,30 @@ class UploadController extends Controller
public function actionUpload()
{
$postdata = fopen( $_FILES[ 'data' ][ 'tmp_name' ], "r" );
// /* Get file extension */
$extension = substr( $_FILES[ 'data' ][ 'name' ], strrpos( $_FILES[ 'data' ][ 'name' ], '.' ) );
$model = new UploadForm();
$resp = [];
if ( $model->load(Yii::$app->request->post()) && $model->validate()) {
$model->image = UploadedFile::getInstance($model, 'image');
/**save into frontend/web/uploads/profile*/
$path = \common\components\Image::upload($model->image,'profile');
$image = new Image();
$image->path = $path;
$image->save();
/* the result object that is sent to client*/
// /* Generate unique name */
$filename = \Yii::getAlias('@frontend') ."/web/profile/" . uniqid() . $extension;
echo $filename;
// /* Open a file for writing */
$fp = fopen( $filename, "w" );
/* Read the data 1 KB at a time
and write to the file */
while( $data = fread( $postdata, 1024 ) )
fwrite( $fp, $data );
/* Close the streams */
fclose( $fp );
fclose( $postdata );
/* the result object that is sent to client*/
echo "ok";
$resp['ok'] = 1;
$resp['id_image'] = $image->id_image;
}else{
$resp['ok'] = 0;
$resp['message'] = print_r($model->errors,true);
}
return $resp;
}
}

View File

@ -3,22 +3,45 @@ namespace backend\models;
use yii\base\Model;
use common\models\User;
use common\models\Image;
class UploadForm extends Model{
const SECRET= "aN6obLS2wMFzXw2VQBar";
public $image ;
public $secret;
/**
* @inheritdoc
* @formatter:off
*/
public function rules()
{
return [['image',function ($attribute, $params) {}], ];
return [
[['image'], 'image', 'mimeTypes' => 'image/jpeg, image/png', 'extensions'=>'jpg, png'],
[['image'], 'required',],
[['secret'], 'required'],
[['secret'], 'validSecret'],
];
}
public function validSecret(){
if ( $this->secret != self::SECRET ){
$this->addError("secret","Invalid secret");
}
}
public function save(){
$image = new Image();
return true;
}
}

View File

@ -13,6 +13,7 @@ use backend\models\UploadForm;
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?php echo $form->field($model, "image")->fileInput()?>
<div class="form-group">
<?= Html::submitButton( Yii::t('common/ticket', 'Create') ,['class' => 'btn btn-primary']) ?>

164
common/components/GD.php Normal file
View File

@ -0,0 +1,164 @@
<?php
namespace common\components;
class GD
{
private $_image;
private $_mime;
private $_width;
private $_height;
public function __construct($file)
{
if (file_exists($file)) {
$imageData = getimagesize($file);
$this->_mime = image_type_to_mime_type($imageData[2]);
$this->_width = $imageData[0];
$this->_height = $imageData[1];
switch ($this->_mime) {
case 'image/jpeg':
$this->_image = imagecreatefromjpeg($file);
break;
case 'image/png':
$this->_image = imagecreatefrompng($file);
break;
case 'image/gif':
$this->_image = imagecreatefromgif($file);
break;
}
}
}
public function resize($width = null, $height = null)
{
if(!$this->_image || (!$width && !$height)){
return false;
}
if(!$width)
{
if ($this->_height > $height) {
$ratio = $this->_height / $height;
$newWidth = round($this->_width / $ratio);
$newHeight = $height;
} else {
$newWidth = $this->_width;
$newHeight = $this->_height;
}
}
elseif(!$height)
{
if ($this->_width > $width) {
$ratio = $this->_width / $width;
$newWidth = $width;
$newHeight = round($this->_height / $ratio);
} else {
$newWidth = $this->_width;
$newHeight = $this->_height;
}
}
else
{
$newWidth = $width;
$newHeight = $height;
}
$resizedImage = imagecreatetruecolor($newWidth, $newHeight);
imagealphablending($resizedImage, false);
imagecopyresampled(
$resizedImage,
$this->_image,
0,
0,
0,
0,
$newWidth,
$newHeight,
$this->_width,
$this->_height
);
$this->_image = $resizedImage;
}
public function cropThumbnail($width, $height)
{
if(!$this->_image || !$width || !$height){
return false;
}
$sourceRatio = $this->_width / $this->_height;
$thumbRatio = $width / $height;
$newWidth = $this->_width;
$newHeight = $this->_height;
if($sourceRatio !== $thumbRatio)
{
if($this->_width >= $this->_height){
if($thumbRatio > 1){
$newHeight = $this->_width / $thumbRatio;
if($newHeight > $this->_height){
$newWidth = $this->_height * $thumbRatio;
$newHeight = $this->_height;
}
} elseif($thumbRatio == 1) {
$newWidth = $this->_height;
$newHeight = $this->_height;
} else {
$newWidth = $this->_height * $thumbRatio;
}
} else {
if($thumbRatio > 1){
$newHeight = $this->_width / $thumbRatio;
} elseif($thumbRatio == 1) {
$newWidth = $this->_width;
$newHeight = $this->_width;
} else {
$newHeight = $this->_width / $thumbRatio;
if($newHeight > $this->_height){
$newHeight = $this->_height;
$newWidth = $this->_height * $thumbRatio;
}
}
}
}
$resizedImage = imagecreatetruecolor($width, $height);
imagealphablending($resizedImage, false);
imagecopyresampled(
$resizedImage,
$this->_image,
0,
0,
round(($this->_width - $newWidth) / 2),
round(($this->_height - $newHeight) / 2),
$width,
$height,
$newWidth,
$newHeight
);
$this->_image = $resizedImage;
}
public function save($file, $quality = 90)
{
switch($this->_mime) {
case 'image/jpeg':
return imagejpeg($this->_image, $file, $quality);
break;
case 'image/png':
imagesavealpha($this->_image, true);
return imagepng($this->_image, $file);
break;
case 'image/gif':
return imagegif($this->_image, $file);
break;
}
return false;
}
}

View File

@ -0,0 +1,99 @@
<?php
namespace common\components;
use Yii;
use yii\web\UploadedFile;
use yii\web\HttpException;
use yii\helpers\FileHelper;
use common\components\GD;
class Image
{
/**
* @param UploadedFile $fileInstance
* @param string $dir relative dir from upload dir
* @param unknown $resizeWidth
* @param unknown $resizeHeight
* @param bool $resizeCrop
* @throws HttpException*/
public static function upload(UploadedFile $fileInstance, $dir = '', $resizeWidth = null, $resizeHeight = null, $resizeCrop = false)
{
$fileName = Upload::getUploadPath($dir) . DIRECTORY_SEPARATOR . Upload::getFileName($fileInstance);
$uploaded = $resizeWidth
? self::copyResizedImage($fileInstance->tempName, $fileName, $resizeWidth, $resizeHeight, $resizeCrop)
: $fileInstance->saveAs($fileName);
if(!$uploaded){
throw new HttpException(500, 'Cannot upload file "'.$fileName.'". Please check write permissions.');
}
return Upload::getLink($fileName);
}
/**
*
* @param unknown $filename
* @param unknown $width
* @param unknown $height
* @param string $crop
* @return string
*/
static function thumb($filename, $width = null, $height = null, $crop = true)
{
if($filename && file_exists(($filename = Yii::getAlias('@frontend/web') . $filename)))
{
$info = pathinfo($filename);
$thumbName = $info['filename'] . '-' . md5( filemtime($filename) . (int)$width . (int)$height . (int)$crop ) . '.' . $info['extension'];
$thumbFile = Yii::getAlias('@frontend/web') . DIRECTORY_SEPARATOR . Upload::$UPLOADS_DIR . DIRECTORY_SEPARATOR . 'thumbs' . DIRECTORY_SEPARATOR . $thumbName;
$thumbWebFile = '/' . Upload::$UPLOADS_DIR . '/thumbs/' . $thumbName;
if(file_exists($thumbFile)){
return $thumbWebFile;
}
elseif(FileHelper::createDirectory(dirname($thumbFile), 0777) && self::copyResizedImage($filename, $thumbFile, $width, $height, $crop)){
return $thumbWebFile;
}
}
return '';
}
static function copyResizedImage($inputFile, $outputFile, $width, $height = null, $crop = true)
{
if (extension_loaded('gd'))
{
$image = new GD($inputFile);
if($height) {
if($width && $crop){
$image->cropThumbnail($width, $height);
} else {
$image->resize($width, $height);
}
} else {
$image->resize($width);
}
return $image->save($outputFile);
}
elseif(extension_loaded('imagick'))
{
$image = new \Imagick($inputFile);
if($height && !$crop) {
$image->resizeImage($width, $height, \Imagick::FILTER_LANCZOS, 1, true);
}
else{
$image->resizeImage($width, null, \Imagick::FILTER_LANCZOS, 1);
}
if($height && $crop){
$image->cropThumbnailImage($width, $height);
}
return $image->writeImage($outputFile);
}
else {
throw new HttpException(500, 'Please install GD or Imagick extension');
}
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace common\components;
use Yii;
use yii\web\UploadedFile;
use \yii\web\HttpException;
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
use yii\helpers\FileHelper;
class Upload
{
public static $UPLOADS_DIR = 'uploads';
public static function file(UploadedFile $fileInstance, $dir = '', $namePostfix = true)
{
$fileName = Upload::getUploadPath($dir) . DIRECTORY_SEPARATOR . Upload::getFileName($fileInstance, $namePostfix);
if(!$fileInstance->saveAs($fileName)){
throw new HttpException(500, 'Cannot upload file "'.$fileName.'". Please check write permissions.');
}
return Upload::getLink($fileName);
}
static function getUploadPath($dir)
{
$uploadPath = $dir = Yii::getAlias('@frontend/web').DIRECTORY_SEPARATOR.self::$UPLOADS_DIR.($dir ? DIRECTORY_SEPARATOR.$dir : '');
if(!FileHelper::createDirectory($uploadPath)){
throw new HttpException(500, 'Cannot create "'.$uploadPath.'". Please check write permissions.');
}
return $uploadPath;
}
static function getLink($fileName)
{
return str_replace('\\', '/', str_replace(Yii::getAlias('@frontend/web'), '', $fileName));
}
static function getFileName($fileInstanse, $namePostfix = true)
{
$baseName = str_ireplace('.'.$fileInstanse->extension, '', $fileInstanse->name);
$fileName = StringHelper::truncate(Inflector::slug($baseName), 32, '');
if($namePostfix || !$fileName) {
$fileName .= ($fileName ? '-' : '') . substr(uniqid(md5(rand()), true), 0, 10);
}
$fileName .= '.' . $fileInstanse->extension;
return $fileName;
}
}

60
common/models/Image.php Normal file
View File

@ -0,0 +1,60 @@
<?php
namespace common\models;
use Yii;
use yii\behaviors\TimestampBehavior;
/**
* This is the model class for table "image".
*
* @property integer $id_image
* @property string $path
* @property string $created_at
* @property string $updated_at
*/
class Image extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'image';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['path'], 'string', 'max' => 255]
];
}
/**
* @inheritdoc
*/
public function behaviors()
{
return [
[ 'class' => TimestampBehavior::className(),
'value' => function(){ return date('Y-m-d H:i:s' ); }
]
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id_image' => Yii::t('common/image', 'Id Image'),
'path' => Yii::t('common/image', 'Path'),
'created_at' => Yii::t('common/image', 'Created At'),
'updated_at' => Yii::t('common/image', 'Updated At'),
];
}
}

View File

@ -0,0 +1,43 @@
<?php
use yii\db\Schema;
use yii\db\Migration;
class m151127_152631_add__table__image extends Migration
{
public function up()
{
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
// http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
}
$this->createTable('{{%image}}', [
'id_image' => $this->primaryKey(),
'path' => $this->string(255),
'created_at' => $this->dateTime()->notNull(),
'updated_at' => $this->dateTime()->notNull(),
], $tableOptions);
}
public function down()
{
echo "m151127_152631_add__table__image cannot be reverted.\n";
return false;
}
/*
// Use safeUp/safeDown to run migration code within a transaction
public function safeUp()
{
}
public function safeDown()
{
}
*/
}

View File

@ -0,0 +1,30 @@
<?php
use yii\db\Schema;
use yii\db\Migration;
class m151127_214503_alter__table__customer__add__column__id_image extends Migration
{
public function up()
{
$this->addColumn("customer", "id_image", "int");
}
public function down()
{
echo "m151127_214503_alter__table__customer__add__column__id_image cannot be reverted.\n";
return false;
}
/*
// Use safeUp/safeDown to run migration code within a transaction
public function safeUp()
{
}
public function safeDown()
{
}
*/
}