Как разблокировать файл после загрузки файла AWS S3 Helper?

Я использую официальный официальный SDK с официальным поставщиком услуг для laravel, чтобы загрузить изображение на Amazon S3. Изображение временно сохраняется на моем сервере и должно быть удалено после загрузки. Ниже приведен код, который я использовал для загрузки и удаления.

$temp_path = "/screenshot_temp/testing.png";

$client = AWS::createClient('s3');
$result = $client->putObject(array(
        'Bucket'     => self::$bucketName,
        'Key'        => 'screenshot/testing.png',
        'SourceFile' => $temp_path,
        'ACL'    => 'public-read'
    ));
);

chown($temp_path, 777);
unlink($temp_path);

Загрузка выполнена успешно. Я вижу изображение с возвратом ссылки, и я вижу это на консоли amazon. Проблема заключается в том, что удаление завершилось неудачно, со следующим сообщением об ошибке:

ErrorException: unlink(... path of my file ...): Permission denied

Я уверен, что мой параметр разрешений для файлов верен, и я могу удалить свой файл с разделом кода для загрузки в комментарий S3. Поэтому проблема заключается в том, что файл заблокирован при загрузке файла. Есть ли способ открыть и удалить файл?

Ответ 1

Да, потоковая загрузка блокирует файл до его завершения, попробуйте выполнить одно из двух,

$client = AWS::createClient('s3');
$fileContent = file_get_contents($temp_path);
$result = $client->putObject(array(
    'Bucket'     => self::$bucketName,
    'Key'        => 'screenshot/testing.png',
    'Body'       => $fileContent,
    'ACL'        => 'public-read'
));
);

unlink($temp_path);

или

$client = AWS::createClient('s3');
$fileContent = file_get_contents($temp_path);
$result = $client->putObject(array(
    'Bucket'     => self::$bucketName,
    'Key'        => 'screenshot/testing.png',
    'Body'       => $fileContent,
    'ACL'        => 'public-read'
));
);

gc_collect_cycles();
unlink($temp_path);

Ответ 2

Когда вы используете параметр SourceFile в putObject, S3Client открывает файл, но не закрывает его после операции.

В большинстве случаев вы можете отключить $client и/или $result, чтобы закрыть открытые файлы. Но к сожалению не в этом случае.

Используйте Body вместо SourceFile.

// temp file
$file = fopen($temp_path, "r");

// use resource, not a path
$result = $client->putObject(array(
        'Bucket'     => self::$bucketName,
        'Key'        => 'screenshot/testing.png',
        'Body'       => $file,
        'ACL'        => 'public-read'
    ));
);

fclose($file);

unlink($temp_path);

Ответ 3

EDIT: Я заметил, что строка в вашем temp_path начинается с символа "/". Эта начальная косая черта обычно начинается в корневом каталоге веб-сайта, вы уверены, что это правильное местоположение? Используйте команду getcwd() в PHP, чтобы узнать, какая папка PHP считает, что она находится внутри.

Я понимаю, что вы считаете, что права правильны, но в свете ошибки "отказа от разрешения" я все еще верю, что он говорит вам что-то важное.

Я вижу, что вы пытаетесь использовать каталог, возможно, вы хотели бы это сделать? Если вы можете использовать SSH на своем сервере и запустить эту команду, вам может быть повезло больше:

chmod -R 777 /(your-website-dir/screenshot_temp

Или попробуйте изменить "chown" на "chmod" в вашем PHP-коде.

Ответ 4

Я не парень PHP, но я бы попробовал выпустить этого плохого мальчика в поток, а затем передать поток в SDK.

Таким образом, вы можете явно закрыть поток, а затем удалить временный файл. Вы даже можете полностью удалить временный файл и работать исключительно с потоками, если это разрешено вашим конкретным прецедентом.

Похоже, это сообщение SO может установить вас на правильный трек.