1

我正在尝试从谷歌云存储中提供大型音频文件并寻求支持。

我很难理解 php fopen 和 google 流包装器一起工作。当 fopen 被调用时,它会立即从谷歌 StreamWrapper 类中调用 stream_open。但是我无法通过 fopen 上下文向它传递选项。我想将按位选项 0b10000 设置为其 STREAM_MUST_SEEK 选项。$flags 参数始终为 0。

https://www.php.net/manual/en/streamwrapper.stream-open

文档显示您可以设置至少两个选项,但它没有说明您可以在哪里设置它们。

没有 $flag 设置为 0b10000 我得到:

PHP Warning:  stream_copy_to_stream(): Failed to seek to position 85721088 in the stream in /home/project/src/Classes/StreamResponse.php on line 296

如果我将 $flags 设置为 0b10000 它可以工作并支持搜索。

$opts = array(
  'gs' => array('key' => 'value')
);

$context = stream_context_create($opts);


$out = fopen('php://output', 'wb');
$file = fopen($this->file->getPathname(), 'rb', false, $context);

stream_copy_to_stream($file, $out, $this->maxlen, $this->offset);

fclose($out);
fclose($file);

/**
 * Callback handler for when a stream is opened. For reads, we need to
 * download the file to see if it can be opened.
 *
 * @param string $path The path of the resource to open
 * @param string $mode The fopen mode. Currently only supports ('r', 'rb', 'rt', 'w', 'wb', 'wt')
 * @param int $flags Bitwise options STREAM_USE_PATH|STREAM_REPORT_ERRORS|STREAM_MUST_SEEK
 * @param string $openedPath Will be set to the path on success if STREAM_USE_PATH option is set
 * @return bool
 */
public function stream_open($path, $mode, $flags, &$openedPath)
{
    $client = $this->openPath($path);

    // strip off 'b' or 't' from the mode
    $mode = rtrim($mode, 'bt');

    $options = [];
    if ($this->context) {
        $contextOptions = stream_context_get_options($this->context);
        if (array_key_exists($this->protocol, $contextOptions)) {
            $options = $contextOptions[$this->protocol] ?: [];
        }
    }

    if ($mode == 'w') {
        $this->stream = new WriteStream(null, $options);
        $this->stream->setUploader(
            $this->bucket->getStreamableUploader(
                $this->stream,
                $options + ['name' => $this->file]
            )
        );
    } elseif ($mode == 'r') {
        try {
            // Lazy read from the source
            $options['restOptions']['stream'] = true;
            $this->stream = new ReadStream(
                $this->bucket->object($this->file)->downloadAsStream($options)
            );

            // Wrap the response in a caching stream to make it seekable
            if (!$this->stream->isSeekable() && ($flags & STREAM_MUST_SEEK)) {
                $this->stream = new CachingStream($this->stream);
            }
        } catch (ServiceException $ex) {
            return $this->returnError($ex->getMessage(), $flags);
        }
    } else {
        return $this->returnError('Unknown stream_open mode.', $flags);
    }

    if ($flags & STREAM_USE_PATH) {
        $openedPath = $path;
    }
    return true;
}
4

0 回答 0