使用php://memory包装器会导致错误。

5

我正在尝试通过扩展Worx的PHP邮件类来添加一个方法,该方法允许我使用字符串数据而不是文件路径添加附件。

我的实现类似于下面这样:

public function addAttachmentString($string, $name='', $encoding = 'base64', $type = 'application/octet-stream')
{
  $path = 'php://memory/' . md5(microtime());
  $file = fopen($path, 'w');
  fwrite($file, $string);
  fclose($file);

  $this->AddAttachment($path, $name, $encoding, $type);
}

然而,我得到的只是一个PHP警告:
PHP Warning:  fopen() [<a href='function.fopen'>function.fopen</a>]: Invalid php:// URL specified

原始文档中没有合适的例子,但我在互联网上找到了一些(包括这里的一个SO问题),并且根据它们的使用情况,我的用法似乎是正确的。

有人使用过这个函数吗?

我的备选方案是创建一个临时文件并进行清理 - 但这将意味着需要写入磁盘,而这个函数将作为大批处理的一部分使用,并且我希望尽可能避免慢速磁盘操作(旧服务器)。这只是一个短文件,但对于脚本发送电子邮件的每个人都有不同的信息。


我太晚了,但是难道不是在fclose()上删除内存缓冲区吗? - Owen Beresford
3个回答

20

它只是php://memory。例如,

<?php
    $path = 'php://memory';
    $h = fopen($path, "rw+");
    fwrite($h, "bugabuga");
    fseek($h, 0);
    echo stream_get_contents($h);
产生"bugabuga"。

请记住,rewind($h);fseek($h, 0); 是相同的! - Vladimir Ch

2

快速查看http://php.net/manual/en/wrappers.php.php和源代码,我没有看到对于"/' . md5(microtime());"的支持。

示例代码:

<?php
print "Trying with md5\n";
$path = 'php://memory/' . md5(microtime());
$file = fopen($path, 'w');
if ($file)
{
    fwrite($file, "blah");
    fclose($file);
}
print "done - with md5\n";

print "Trying without md5\n";
$path = 'php://memory';
$file = fopen($path, 'w');
if ($file)
{
    fwrite($file, "blah");
    fclose($file);
}
print "done - no md5\n";

输出:

buzzbee ~$ php test.php 
Trying with md5

Warning: fopen(): Invalid php:// URL specified in test.php on line 4

Warning: fopen(php://memory/d2a0eef34dff2b8cc40bca14a761a8eb): failed to open stream: operation failed in test.php on line 4
done - with md5
Trying without md5
done - no md5

嗯...是的,我也尝试过这个 - 我遇到的一个问题是我没有附加内容。这可能是因为phpmailer对此使用了错误的方法...我刚刚意识到phpmailer中已经有一个AddStringAttachment方法(解决了即时问题)- 但了解php://memory包装器也很好。 - HorusKol
$path = 'php://memory/' . md5(microtime()); 会破坏一切,你需要使用 $path = 'php://memory';。 - Jaro
它失败了,因为你正在关闭文件描述符,正如手册中所写!php://memory和php://temp不可重复使用,即在流被关闭后,无法再次引用它们。请使用rewind($file);代替fclose($file); - Vladimir Ch

1
这里的问题简单来说 就是类型和语法

php://memoryphp://temp读写流,允许将临时数据存储在类似文件的包装器中。两者之间唯一的区别是 php://memory 总是将其数据存储在内存中,而 php://temp 会在存储的数据量达到预定义限制时使用临时文件(默认为2 MB)。此临时文件的位置与sys_get_temp_dir()函数相同。

简而言之,您需要的类型是temp,而您需要的语法是:

php://temp/maxmemory:$limit
$limit 是以字节为单位的。您想使用安全字节函数进行计数。

1
如果我使用类似 fopen('php://temp/maxmemory:1048576', 'w') 这样的东西,那么我的“filepath”将是什么?整个 "'php://temp/maxmemory:1048576'" 吗?我需要在其他函数中使用此文件路径。谢谢。 - Andrew
@Andrew 检查 sys_get_temp_dir() … 或者更好的方法是:打开一个新问题,引用这个问题并在那里回答。 - kaiser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接