Я использую систему flysystem с очередью IRON IO и пытаюсь выполнить запрос к базе данных, который будет содержать ~ 1,8 миллиона записей и 5000 одновременно. Вот сообщение об ошибке, которое я получаю с размером файла более 50 МБ:
PHP Fatal error: Allowed memory size of ########## bytes exhausted
Вот шаги, которые я хотел бы предпринять:
1) Получить данные
2) Превратите его в соответствующую строку CSV (т.е. implode(',', $dataArray) . "\r\n"
)
3) Получить файл с сервера (в данном случае S3)
4) Считайте содержимое этих файлов, добавьте в него эту новую строку и перезаписайте это содержимое в файл S3.
Вот краткий обзор кода, который у меня есть:
public function fire($job, $data)
{
// First set the headers and write the initial file to server
$this->filesystem->write($this->filename, implode(',', $this->setHeaders($parameters)) . "\r\n", [
'visibility' => 'public',
'mimetype' => 'text/csv',
]);
// Loop to get new sets of data
$offset = 0;
while ($this->exportResult) {
$this->exportResult = $this->getData($parameters, $offset);
if ($this->exportResult) {
$this->writeToFile($this->exportResult);
$offset += 5000;
}
}
}
private function writeToFile($contentToBeAdded = '')
{
$content = $this->filesystem->read($this->filename);
// Append new data
$content .= $contentToBeAdded;
$this->filesystem->update($this->filename, $content, [
'visibility' => 'public'
]);
}
Я предполагаю, что это не самый эффективный? Я ухожу из этих документов:
PHPLeague Flysystem
Если кто-нибудь может указать мне более подходящее направление, это было бы здорово!
Если вы работаете с S3, я бы использовал AWS SDK для PHP напрямую для решения этой конкретной проблемы. Присоединиться к файлу на самом деле очень просто, используя потоковую упаковку SDK S3, и не заставляет вас читать весь файл в память.
$s3 = \Aws\S3\S3Client::factory($clientConfig);
$s3->registerStreamWrapper();
$appendHandle = fopen("s3://{$bucket}/{$key}", 'a');
fwrite($appendHandle, $data);
fclose($appendHandle);
Flysystem поддерживает поток чтения / записи / обновления
Пожалуйста, проверьте последний API https://flysystem.thephpleague.com/api/
$stream = fopen('/path/to/database.backup', 'r+');
$filesystem->writeStream('backups/'.strftime('%G-%m-%d').'.backup', $stream);
// Using write you can also directly set the visibility
$filesystem->writeStream('backups/'.strftime('%G-%m-%d').'.backup', $stream, [
'visibility' => AdapterInterface::VISIBILITY_PRIVATE
]);
if (is_resource($stream)) {
fclose($stream);
}
// Or update a file with stream contents
$filesystem->updateStream('backups/'.strftime('%G-%m-%d').'.backup', $stream);
// Retrieve a read-stream
$stream = $filesystem->readStream('something/is/here.ext');
$contents = stream_get_contents($stream);
fclose($stream);
// Create or overwrite using a stream.
$putStream = tmpfile();
fwrite($putStream, $contents);
rewind($putStream);
$filesystem->putStream('somewhere/here.txt', $putStream);
if (is_resource($putStream)) {
fclose($putStream);
}