В моей форме есть простой элемент управления HTML-файлом. Это динамический характер, означает, что пользователь может загрузить один или несколько файлов. Его HTML выглядит следующим образом:
<input type="file" id="image_book" class="image_book upload" name="image[]" accept="image/*" value=""/>
Если я загружаю два изображения, используя вышеуказанный элемент управления HTML-файлом, и отправляю форму, я получаю следующее $_FILES
массив (выход print_r($_FILES);
):
Array
(
[image] => Array
(
[name] => Array
(
[0] => Aurbd-b3582991-large.jpg
[1] => BL_Miller_GD_Square_KV_300dpi_A2.jpg
)
[type] => Array
(
[0] => image/jpeg
[1] => image/jpeg
)
[tmp_name] => Array
(
[0] => /tmp/phpSt8CJJ
[1] => /tmp/phpibFjR2
)
[error] => Array
(
[0] => 0
[1] => 0
)
[size] => Array
(
[0] => 519179
[1] => 86901
)
)
)
Теперь в соответствии с новым требованием я должен использовать Filepicker вместо простого элемента управления HTML File / s для загрузки файлов на сервер. Но проблема, с которой я сталкиваюсь, заключается в том, что дальнейшая логика кода и манипуляции уже были написаны с учетом вышеуказанного массива$_FILES
) содержание.
Итак, я хочу преобразовать запрос, поступающий через Filepicker, в тот же формат, что и массив $_FILES
чтобы не было необходимости вносить какие-либо изменения в логику и манипуляции с уже написанным кодом.
Позвольте мне объяснить вам сценарий более четко: если пользователь выбирает один или несколько файлов изображений из Google Диска через Filepicker и отправляет форму, запрос будет содержать URL-адреса тех изображений, которые генерируются Filepicker, и имена файлов.
Я хочу использовать эти данные и сформировать массив как вышеупомянутый массив ($_FILES
).
Предполагая, что вы используете PHP 5.2.1 или выше и можете использовать обертку потока HTTPS в copy()
а также file_get_contents()
эта функция должна быть все, что вам нужно:
function getFilepickerFiles($tokens)
{
$files = array('name' => array(),
'type' => array(),
'tmp_name' => array(),
'error' => array(),
'size' => array());
$tmpdir = sys_get_temp_dir();
foreach($tokens as $token)
{
$files['tmp_name'][] = $tmp = $tmpdir.'/php'.$token;
$files['error'][] = copy('https://www.filepicker.io/api/file/'.$token, $tmp) ? UPLOAD_ERR_OK : UPLOAD_ERR_NO_FILE;
$files['size'][] = filesize($tmp);
$meta = json_decode(file_get_contents('https://www.filepicker.io/api/file/'.$token.'/metadata?filename=true&mimetype=true'), TRUE);
$files['name'][] = $meta['filename'];
$files['type'][] = $meta['mimetype'];
}
return array('image' => $files);
}
Эта функция принимает массив токенов (таких как hFHUCB3iTxyMzseuWOgG
в качестве аргумента.
Вы можете назвать это как
getFilepickerFiles(array('hFHUCB3iTxyMzseuWOgG'));
Я не знаю точно, что Filepicker передает на ваш сервер, но если это полный URL-адрес файла, например
https://www.filepicker.io/api/file/hFHUCB3iTxyMzseuWOgG
тогда вы можете извлечь токены следующим образом:
$tokens = array();
foreach($urls as $url)
{
$matches = array();
preg_match('# ^https://www\\.filepicker\\.io/api/file/([^/]*)/?', $url, $matches);
$tokens[] = $matches[1];
}
// Pass $tokens to getFilepickerFiles()
Вы также можете поместить это прямо в getFilepickerFiles()
чтобы заставить его принять массив URL файлов:
function getFilepickerFiles($urls)
{
$files = array('name' => array(),
'type' => array(),
'tmp_name' => array(),
'error' => array(),
'size' => array());
$tmpdir = sys_get_temp_dir();
foreach($urls as $url)
{
$matches = array();
preg_match('# ^https://www\\.filepicker\\.io/api/file/([^/]*)/?', $url, $matches);
$token = $matches[1];
$files['tmp_name'][] = $tmp = $tmpdir.'/php'.$token;
$files['error'][] = copy('https://www.filepicker.io/api/file/'.$token, $tmp) ? UPLOAD_ERR_OK : UPLOAD_ERR_NO_FILE;
$files['size'][] = filesize($tmp);
$meta = json_decode(file_get_contents('https://www.filepicker.io/api/file/'.$token.'/metadata?filename=true&mimetype=true'), TRUE);
$files['name'][] = $meta['filename'];
$files['type'][] = $meta['mimetype'];
}
return array('image' => $files);
}
Я чувствую, что приведенный выше код довольно прост, но вот как getFilepickerFiles()
работает (вы должны были прочитать Остальная API документация перед прочтением)
$files = array('name' => array(),
'type' => array(),
'tmp_name' => array(),
'error' => array(),
'size' => array());
инициализировать $files
к массиву, как $_FILES
не содержит файлов.
$tmpdir = sys_get_temp_dir();
Получите каталог, в котором хранятся временные файлы, потому что мы собираемся загрузить туда файлы (для этой функции требуется PHP 5.2.1 или выше).
foreach($urls as $url)
Какие foreach
должно быть ясно.
$files['tmp_name'][] = $tmp = $tmpdir.'/php'.$token;
Создайте наш временный путь к файлу, следуя шаблону $_FILES
(то есть путь к папке временных файлов, строка «php» и некоторые случайные символы).
Это имя мы присваиваем $tmp
(для более простого последующего использования), и мы добавляем его в список путей к файлам.
$files['error'][] = (int)(!copy('https://www.filepicker.io/api/file/'.$token, $tmp));
Попытка загрузить файл в $tmp
используя copy()
с URL-адресом в качестве источника.
Значение, возвращаемое copy()
является TRUE
на успех и FALSE
на провал.
Значения ошибок присутствуют в $_FILES
являются UPLOAD_ERR_OK
в случае успеха и любой другой ценности в противном случае (источник, Я иду с UPLOAD_ERR_NO_FILE
здесь в случае неудачи).
Таким образом, чтобы назначить значимое значение ошибки, мы используем троичный оператор для добавления UPLOAD_ERR_OK
к списку кодов ошибок, если copy()
возвращается TRUE
, а также UPLOAD_ERR_NO_FILE
иначе.
$files['size'][] = filesize($tmp);
Запросите размер файла и добавьте его в список размеров файлов.
$meta = json_decode(file_get_contents('https://www.filepicker.io/api/file/'.$token.'/metadata?filename=true&mimetype=true'), TRUE);
Получить метаданные файла, используя URL в качестве аргумента file_get_contents()
, который должен возвращать массив JSON, который мы декодируем в ассоциативный массив, используя json_decode(/*...*/, TRUE)
,
Так как мы добавили &filename=true&mimetype=true
до конца URL мы получим только значения filename
а также mimetype
— нам не нужно все остальное.
Декодированный массив, который мы назначаем $meta
;
$files['name'][] = $meta['filename'];
$files['type'][] = $meta['mimetype'];
Добавьте значения filename
а также mimetype
от только что декодированного массива JSON до списков имен файлов и типов MIME соответственно.
return array('image' => $files);
Вернуть массив с image
ключ, указывающий на массив файлов, которые мы создали.
И мы сделали.
Я не собираюсь создавать целый веб-сайт для размещения файлов, потому что для написания этого ответа потребуется в пять раз больше времени.
Поэтому я боюсь, что не смогу предоставить вам полностью работающее живое демо.
К сожалению, ни 3v4l ни codepad включите потоковую упаковку HTTPS, так что я даже не могу предоставить вам демонстрацию концепции «посмотрите сами».
Лучшее, что я могу сделать, — это, вероятно, скриншот окна моего терминала (нажмите, чтобы увеличить):
Других решений пока нет …