0

I am adding multiple files to a ZipArchive each file has a unique name.

Controller:

$zip = new ZipArchive();
$zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$filesToClose = $this->advancedService->addFiles($files, $zip);
$zip->close();

foreach ($filesToClose as $file) {
    fclose($file);
    unlink(stream_get_meta_data($file)['uri']);
}
// return response

Service:

// addFiles function
foreach ($files as $file) {
    $fileName = 'FILE_'.$file->getId().'.'.$file->getExtension();

    $tempFile = tmpfile();
    $content = file_get_contents('uriFromSdk');
    fwrite($tempFile, $content);
    $zipArchive->addFile(stream_get_meta_data($tempFile)['uri'], $fileName);

    $filesToClose[] = $tempFile;
}

return $filesToClose;

In controller I get this error:

stream_get_meta_data(): supplied resource is not a valid stream resource

The main problem is I can not close or delete any file before $zip->close(), How can I unlink the files from the server ?

Keep in mind fclose() doesn't throw this error, only the stream_get_meta_data().

Thanks.

gp_sflover
  • 3,460
  • 5
  • 38
  • 48
talhaamir
  • 99
  • 2
  • 15
  • What does reversing order of `fclose` and `unlink` do? First `unlink` then `fclose`? [`stream_get_meta_data`](https://www.php.net/manual/en/function.stream-get-meta-data.php) requires an active stream. – bloodyKnuckles Jun 14 '22 at 09:54
  • I have not tried that, do you think it matters ? if yes can you please explain thanks. – talhaamir Jun 14 '22 at 09:57

2 Answers2

3

Reverse order of fclose and unlink. First unlink then fclose. stream_get_meta_data requires an active stream.

Returns information about an existing stream.

foreach ($filesToClose as $file) {
    unlink(stream_get_meta_data($file)['uri']);
    fclose($file);
}
bloodyKnuckles
  • 11,551
  • 3
  • 29
  • 37
1

bloodyKnuckles's answer about stream_get_meta_data is correct, but as far as I know unlink can be done if the file is not used/busy. So you may need like this:

foreach ($filesToClose as $file) {
    $filepath = stream_get_meta_data($file)['uri'];
    fclose($file);
    unlink($filepath);
}

If it still has an error, try adding gc_collect_cycles() after fclose:

foreach ($filesToClose as $file) {
    $filepath = stream_get_meta_data($file)['uri'];
    fclose($file);
    gc_collect_cycles();
    unlink($filepath);
}

reference

Muhammad Dyas Yaskur
  • 6,914
  • 10
  • 48
  • 73