从临时文件流式传输,完成后删除?
Stream from a temporary file, then delete when finished?
我正在通过 运行 几个外部 Unix 工具在 PDF 文件上编写一个临时文件(基本上我使用 QPDF 和 sed 来改变颜色值。不要问。):
// Uncompress PDF using QPDF (doesn't read from stdin, so needs tempfile.)
$compressed_file_path = tempnam(sys_get_temp_dir(), 'cruciverbal');
file_put_contents($compressed_file_path, $response->getBody());
$uncompressed_file_path = tempnam(sys_get_temp_dir(), 'cruciverbal');
$command = "qpdf --qdf --object-streams=disable '$compressed_file_path' '$uncompressed_file_path'";
exec($command, $output, $return_value);
// Run through sed (could do this bit with streaming stdin/stdout)
$fixed_file_path = tempnam(sys_get_temp_dir(), 'cruciverbal');
$command = "sed s/0.298039215/0.0/g < '$uncompressed_file_path' > '$fixed_file_path'";
exec($command, $output, $return_value);
所以,当这完成后,我在 $fixed_file_path
的磁盘上留下了一个临时文件。 (注意:虽然我可以在没有临时文件的情况下在内存中执行整个 sed
流程,但 QPDF 实用程序 requires an actual file as input 有充分的理由。)
在我现有的流程中,然后我将整个 $fixed_file_path
文件作为一个字符串读入,将其删除,然后将该字符串交给另一个 class 去处理。
我现在想将最后一部分更改为使用 PSR-7 流,即 \Guzzle\Psr7\Stream
对象。我认为它会更节省内存(我可能会同时播放其中的一些)并且最终需要成为一个流。
但是,我不确定当(第三方)class 我将流交给它时我将如何删除临时文件。有没有一种方法可以说“......并在你完成后删除它”?或者以其他方式自动清理我的临时文件,而无需手动跟踪它们?
我一直在模糊地考虑推出自己的 SelfDestructingFileStream
,但这似乎有些过分,我想我可能会遗漏一些东西。
听起来你想要的是这样的:
<?php
class TempFile implements \Psr\Http\Message\StreamInterface {
private $resource;
public function __construct() {
$this->resource = tmpfile();
}
public function __destruct() {
$this->close();
}
public function getFilename() {
return $this->getMetadata('uri');
}
public function getMetadata($key = null) {
$data = stream_get_meta_data($this->resource);
if($key) {
return $data[$key];
}
return $data;
}
public function close() {
fclose($this->resource);
}
// TODO: implement methods from https://github.com/php-fig/http-message/blob/master/src/StreamInterface.php
}
让 QPDF 写入 $tmpFile->getFilename()
,然后您可以将整个对象传递给您的 Guzzle/POST,因为它符合 PSR-7,然后文件将在超出范围时自行删除。
我正在通过 运行 几个外部 Unix 工具在 PDF 文件上编写一个临时文件(基本上我使用 QPDF 和 sed 来改变颜色值。不要问。):
// Uncompress PDF using QPDF (doesn't read from stdin, so needs tempfile.)
$compressed_file_path = tempnam(sys_get_temp_dir(), 'cruciverbal');
file_put_contents($compressed_file_path, $response->getBody());
$uncompressed_file_path = tempnam(sys_get_temp_dir(), 'cruciverbal');
$command = "qpdf --qdf --object-streams=disable '$compressed_file_path' '$uncompressed_file_path'";
exec($command, $output, $return_value);
// Run through sed (could do this bit with streaming stdin/stdout)
$fixed_file_path = tempnam(sys_get_temp_dir(), 'cruciverbal');
$command = "sed s/0.298039215/0.0/g < '$uncompressed_file_path' > '$fixed_file_path'";
exec($command, $output, $return_value);
所以,当这完成后,我在 $fixed_file_path
的磁盘上留下了一个临时文件。 (注意:虽然我可以在没有临时文件的情况下在内存中执行整个 sed
流程,但 QPDF 实用程序 requires an actual file as input 有充分的理由。)
在我现有的流程中,然后我将整个 $fixed_file_path
文件作为一个字符串读入,将其删除,然后将该字符串交给另一个 class 去处理。
我现在想将最后一部分更改为使用 PSR-7 流,即 \Guzzle\Psr7\Stream
对象。我认为它会更节省内存(我可能会同时播放其中的一些)并且最终需要成为一个流。
但是,我不确定当(第三方)class 我将流交给它时我将如何删除临时文件。有没有一种方法可以说“......并在你完成后删除它”?或者以其他方式自动清理我的临时文件,而无需手动跟踪它们?
我一直在模糊地考虑推出自己的 SelfDestructingFileStream
,但这似乎有些过分,我想我可能会遗漏一些东西。
听起来你想要的是这样的:
<?php
class TempFile implements \Psr\Http\Message\StreamInterface {
private $resource;
public function __construct() {
$this->resource = tmpfile();
}
public function __destruct() {
$this->close();
}
public function getFilename() {
return $this->getMetadata('uri');
}
public function getMetadata($key = null) {
$data = stream_get_meta_data($this->resource);
if($key) {
return $data[$key];
}
return $data;
}
public function close() {
fclose($this->resource);
}
// TODO: implement methods from https://github.com/php-fig/http-message/blob/master/src/StreamInterface.php
}
让 QPDF 写入 $tmpFile->getFilename()
,然后您可以将整个对象传递给您的 Guzzle/POST,因为它符合 PSR-7,然后文件将在超出范围时自行删除。