你如何在CakePHP中获得所有上传的文件?

时间:2023-01-15 09:46:16

How do you get all uploaded files in CakePHP 3.x? Here is my controller to get you on track.

如何在CakePHP 3.x中获取所有上传的文件?这是我的控制器让你走上正轨。

<?php
class MyController extends AppController {
    public function upload() {
        // how to loop through all files?
    }
}

Sample form

<form action="/my/upload" method="post" enctype="multipart/form-data">
    <input type="text">
    <!-- any number of file inputs -->
    <input type="file" name="file">
    <input type="file" name="image[]">
    <textarea></textarea>
    <!-- etc. -->
    <input type="submit" value="Upload">
</form>

2 个解决方案

#1


File upload data isn't stored separately anymore, so if you don't know the names (for whatever reasons), and only have this one blob of data, then you'll have to iterate over it and figure which entry is a file upload array, something like you've shown in your answer.

文件上传数据不再单独存储,所以如果您不知道名称(无论出于何种原因),并且只有这一个数据blob,那么您将不得不迭代它并确定哪个条目是文件上传数组,就像你在答案中所显示的一样。

Personally I've used custom request classes instead in such cases. Here's a simple example where the keys of the processed files data are stored and used for extracting the file uploads afterwards.

我个人在这种情况下使用了自定义请求类。这是一个简单的例子,其中存储处理过的文件数据的密钥,然后用于提取文件上传。

namespace App\Network;

class Request extends \Cake\Network\Request {

    /**
     * Holds the keys that are being used to store the file uploads
     * in the data array.
     *
     * @var string[]
     */
    protected $_fileKeys = [];

    /**
     * Returns all file uploads.
     *
     * @return array[]
     */
    public function files() {
        return array_intersect_key($this->data, array_flip($this->_fileKeys));
    }

    protected function _processFiles($post, $files) {
        $filesData = parent::_processFiles([], $files);
        $this->_fileKeys = array_keys($filesData);
        return array_merge($post, $filesData);
    }

}

webroot/index.php

$dispatcher = DispatcherFactory::create();
$dispatcher->dispatch(
    \App\Network\Request::createFromGlobals(),
    new Response()
);

#2


Answer to my own question. I'm not accepting it yet in case someone comes up with something better or finds a bug.

回答我自己的问题。我不接受它,以防万一有人提出更好的东西或发现一个错误。

<?php
class MyController extends AppController {
    public function upload() {
        $files = $this->getFilesArray($this->request->data);
        foreach($files as $file) {
            // move_uploaded_file
        }
    }

    /**
     * Get files recursively in flat array
     *
     * @param mixed $field
     * @return array
     */
    public function getFilesArray($field) {

        if(is_array($field)) {
            if(!empty($field['tmp_name'])) {
                return [$field];
            }
            $files = [];
            foreach($field as $item) {
                $files = array_merge($files, $this->getFilesArray($item));
            }
            return $files;
        }

        return [];
    }

}

#1


File upload data isn't stored separately anymore, so if you don't know the names (for whatever reasons), and only have this one blob of data, then you'll have to iterate over it and figure which entry is a file upload array, something like you've shown in your answer.

文件上传数据不再单独存储,所以如果您不知道名称(无论出于何种原因),并且只有这一个数据blob,那么您将不得不迭代它并确定哪个条目是文件上传数组,就像你在答案中所显示的一样。

Personally I've used custom request classes instead in such cases. Here's a simple example where the keys of the processed files data are stored and used for extracting the file uploads afterwards.

我个人在这种情况下使用了自定义请求类。这是一个简单的例子,其中存储处理过的文件数据的密钥,然后用于提取文件上传。

namespace App\Network;

class Request extends \Cake\Network\Request {

    /**
     * Holds the keys that are being used to store the file uploads
     * in the data array.
     *
     * @var string[]
     */
    protected $_fileKeys = [];

    /**
     * Returns all file uploads.
     *
     * @return array[]
     */
    public function files() {
        return array_intersect_key($this->data, array_flip($this->_fileKeys));
    }

    protected function _processFiles($post, $files) {
        $filesData = parent::_processFiles([], $files);
        $this->_fileKeys = array_keys($filesData);
        return array_merge($post, $filesData);
    }

}

webroot/index.php

$dispatcher = DispatcherFactory::create();
$dispatcher->dispatch(
    \App\Network\Request::createFromGlobals(),
    new Response()
);

#2


Answer to my own question. I'm not accepting it yet in case someone comes up with something better or finds a bug.

回答我自己的问题。我不接受它,以防万一有人提出更好的东西或发现一个错误。

<?php
class MyController extends AppController {
    public function upload() {
        $files = $this->getFilesArray($this->request->data);
        foreach($files as $file) {
            // move_uploaded_file
        }
    }

    /**
     * Get files recursively in flat array
     *
     * @param mixed $field
     * @return array
     */
    public function getFilesArray($field) {

        if(is_array($field)) {
            if(!empty($field['tmp_name'])) {
                return [$field];
            }
            $files = [];
            foreach($field as $item) {
                $files = array_merge($files, $this->getFilesArray($item));
            }
            return $files;
        }

        return [];
    }

}