cakePHP 3.0 上传图片

cakePHP 3.0 uploading images

我想在我的 cakephp 3.0 应用程序中上传图片。但我收到错误消息:

Notice (8): Undefined index: Images [APP/Controller/ImagesController.php, line 55]

cakePHP 3.0 中是否已经有一些上传文件(一次上传多个文件)的示例?因为我只能找到 cakePHP 2.x 的示例!

我想我需要在 ImagesTable.php 中添加自定义验证方法?但是我无法让它工作。

ImagesTable

public function initialize(array $config) {
    $validator
       ->requirePresence('image_path', 'create')
       ->notEmpty('image_path')
       ->add('processImageUpload', 'custom', [
          'rule' => 'processImageUpload'
       ])
}

public function processImageUpload($check = array()) {
    if(!is_uploaded_file($check['image_path']['tmp_name'])){
       return FALSE;
    }
    if (!move_uploaded_file($check['image_path']['tmp_name'], WWW_ROOT . 'img' . DS . 'images' . DS . $check['image_path']['name'])){
        return FALSE;
    }
    $this->data[$this->alias]['image_path'] = 'images' . DS . $check['image_path']['name'];
    return TRUE;
}

ImagesController

public function add()
    {
        $image = $this->Images->newEntity();
        if ($this->request->is('post')) {
            $image = $this->Images->patchEntity($image, $this->request->data);

            $data = $this->request->data['Images'];
            //var_dump($this->request->data);
            if(!$data['image_path']['name']){
                unset($data['image_path']);
            }

            // var_dump($this->request->data);
            if ($this->Images->save($image)) {
                $this->Flash->success('The image has been saved.');
                return $this->redirect(['action' => 'index']);
            } else {
                $this->Flash->error('The image could not be saved. Please, try again.');
            }
        }
        $images = $this->Images->Images->find('list', ['limit' => 200]);
        $projects = $this->Images->Projects->find('list', ['limit' => 200]);
        $this->set(compact('image', 'images', 'projects'));
        $this->set('_serialize', ['image']);
    }

图片add.ctp

<?php
   echo $this->Form->input('image_path', [
      'label' => 'Image',
      'type' => 'file'
      ]
   );
?>

图像实体

protected $_accessible = [
    'image_path' => true,
];

也许以下内容会有所帮助。一个让你轻松上传文件的行为!

http://cakemanager.org/docs/utils/1.0/behaviors/uploadable/

如果您遇到困难,请告诉我。

问候

既然大家都在这里为自己的插件做广告,那我也来做一下吧。我已经检查了另一个问题中链接的可上传行为,它非常简单,看起来已经完成了一半。

如果您想要一个可在企业级扩展的完整解决方案,请检查 FileStorage out. It has some features I haven't seen in any other implementations yet like taking care of ensuring your won't run into file system limitations in the case you get really many files. It works together with Imagine to process the images. You can use each alone or in combination, this follows SoC

它完全基于事件,您可以通过实现自己的事件侦听器来改变一切。它需要一些中等水平的 CakePHP 经验。

有一个quick start guide,看看实现它是多么容易。下面的代码摘自它,是一个完整的例子,请看快速入门指南,比较详细。

class Products extends Table {
    public function initialize() {
        parent::initialize();
        $this->hasMany('Images', [
            'className' => 'ProductImages',
            'foreignKey' => 'foreign_key',
            'conditions' => [
                'Documents.model' => 'ProductImage'
            ]
        ]);
        $this->hasMany('Documents', [
            'className' => 'FileStorage.FileStorage',
            'foreignKey' => 'foreign_key',
            'conditions' => [
                'Documents.model' => 'ProductDocument'
            ]
        ]);
    }
}

class ProductsController extends ApController {
    // Upload an image
    public function upload($productId = null) {
        if (!$this->request->is('get')) {
            if ($this->Products->Images->upload($productId, $this->request->data)) {
                $this->Session->set(__('Upload successful!');
            }
        }
    }
}

class ProductImagesTable extends ImageStorageTable {
    public function uploadImage($productId, $data) {
        $data['adapter'] = 'Local';
        $data['model'] = 'ProductImage',
        $data['foreign_key'] = $productId;
        $entity = $this->newEntity($data);
        return $this->save($data);
    }
    public function uploadDocument($productId, $data) {
        $data['adapter'] = 'Local';
        $data['model'] = 'ProductDocument',
        $data['foreign_key'] = $productId;
        $entity = $this->newEntity($data);
        return $this->save($data);
    }
}
/*Path to Images folder*/
$dir = WWW_ROOT . 'img' .DS. 'thumbnail';
/*Explode the name and ext*/
                $f = explode('.',$data['image']['name']);
                 $ext = '.'.end($f);
    /*Generate a Name in my case i use ID  & slug*/
                $filename = strtolower($id."-".$slug);

     /*Associate the name to the extension  */
                $image = $filename.$ext;


/*Initialize you object and update you table in my case videos*/
                $Videos->image = $image;     
            if ($this->Videos->save($Videos)) {
/*Save image in the thumbnail folders and replace if exist */
            move_uploaded_file($data['image']['tmp_name'],$dir.DS.$filename.'_o'.$ext);

            unlink($dir.DS.$filename.'_o'.$ext);
                } 
<?php
namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use Cake\Network\Exception\InternalErrorException;
use Cake\Utility\Text;

/**
 * Upload component
 */
class UploadRegCompanyComponent extends Component
{

    public $max_files = 1;


    public function send( $data )
    {
        if ( !empty( $data ) ) 
        {
            if ( count( $data ) > $this->max_files ) 
            {
                throw new InternalErrorException("Error Processing Request. Max number files accepted is {$this->max_files}", 1);
            }

            foreach ($data as $file) 
            {
                $filename = $file['name'];
                $file_tmp_name = $file['tmp_name'];
                $dir = WWW_ROOT.'img'.DS.'uploads/reg_companies';
                $allowed = array('png', 'jpg', 'jpeg');
                if ( !in_array( substr( strrchr( $filename , '.') , 1 ) , $allowed) ) 
                {
                    throw new InternalErrorException("Error Processing Request.", 1);       
                }
                elseif( is_uploaded_file( $file_tmp_name ) )
                {
                    move_uploaded_file($file_tmp_name, $dir.DS.Text::uuid().'-'.$filename);
                }
            }
        }
    }
}

在你的视图文件中,像这样添加,在我的例子中是 Users/dashboard.ctp

<div class="ChImg">
<?php 
echo $this->Form->create($particularRecord, ['enctype' => 'multipart/form-data']);
echo $this->Form->input('upload', ['type' => 'file']);
echo $this->Form->button('Update Details', ['class' => 'btn btn-lg btn-success1 btn-block padding-t-b-15']);
echo $this->Form->end();       
?>
</div>

在你的控制器中这样添加,在我的例子中 UsersController

if (!empty($this->request->data)) {
if (!empty($this->request->data['upload']['name'])) {
$file = $this->request->data['upload']; //put the data into a var for easy use

$ext = substr(strtolower(strrchr($file['name'], '.')), 1); //get the extension
$arr_ext = array('jpg', 'jpeg', 'gif'); //set allowed extensions
$setNewFileName = time() . "_" . rand(000000, 999999);

//only process if the extension is valid
if (in_array($ext, $arr_ext)) {
    //do the actual uploading of the file. First arg is the tmp name, second arg is 
    //where we are putting it
    move_uploaded_file($file['tmp_name'], WWW_ROOT . '/upload/avatar/' . $setNewFileName . '.' . $ext);

    //prepare the filename for database entry 
    $imageFileName = $setNewFileName . '.' . $ext;
    }
}

$getFormvalue = $this->Users->patchEntity($particularRecord, $this->request->data);

if (!empty($this->request->data['upload']['name'])) {
            $getFormvalue->avatar = $imageFileName;
}


if ($this->Users->save($getFormvalue)) {
   $this->Flash->success('Your profile has been sucessfully updated.');
   return $this->redirect(['controller' => 'Users', 'action' => 'dashboard']);
   } else {
   $this->Flash->error('Records not be saved. Please, try again.');
   }
}

在使用它之前,在 webroot 中创建一个名为 upload/avatar.

的文件夹

注意:输入('Name Here'),用于

$this->request->data['upload']['name']

想看数组结果可以打印出来

它在 CakePHP 3.x

中就像一个魅力

我们在生产应用中使用 https://github.com/josegonzalez/cakephp-upload 并取得了巨大成功,并且已经使用了相当长一段时间。

对使用 "Flysystem" (https://flysystem.thephpleague.com/) 也有很好的支持——这是对特定文件系统的抽象——所以从普通的本地文件系统迁移到 S3 是一个明智的选择, 或 Dropbox 或任何你想要的地方:-)

您可以在此处找到有关文件上传的相关(高质量)插件:https://github.com/FriendsOfCake/awesome-cakephp#files - 我也成功地使用了 "Proffer",但绝不是 "almost done"或类似的东西 - 两者都有我的所有建议,并且在我看来已经准备好生产了!