Stream_Copy_To_Stream()php的替代品

6 php memory upload copy stream

我正在开发一个文件共享站点,但我遇到了一个小问题.我正在使用上传脚本uploadify,它可以很好地工作,但如果用户希望我希望上传的文件被加密.现在我有工作代码,如下所示,但我的服务器只有1GB或内存,并使用stream_copy_to_stream似乎占用内存中的实际文件的大小,我的最大上传大小是256所以我知道一个事实是坏事当网站上线并且多个人一次上传大文件时,将会发生这种情况.基于我的下面的代码是否有任何替代,几乎没有使用和内存或根本没有,我甚至不关心,如果它需要更长的时间,我只需要这个工作.我有这个工作的下载版本,因为我有文件直接解密,并立即传递到浏览器,所以它解密,因为它下载,虽然我很高效,但这个上传问题看起来不太好.任何帮助表示赞赏.

$temp_file = $_FILES['Filedata']['tmp_name'];
    $ext = pathinfo($_FILES['Filedata']['name'], PATHINFO_EXTENSION);
    $new_file_name = md5(uniqid(rand(), true));
    $target_file = rtrim(enc_target_path, '/') . '/' . $new_file_name . '.enc.' . $ext;

    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $key = substr(md5('some_salt' . $password, true) . md5($password . 'more_salt', true), 0, 24);
    $opts = array('iv' => $iv, 'key' => $key);

    $my_file = fopen($temp_file, 'rb');

    $encrypted_file_name = $target_file;
    $encrypted_file = fopen($encrypted_file_name, 'wb');

    stream_filter_append($encrypted_file, 'mcrypt.rijndael_128', STREAM_FILTER_WRITE, $opts);
    stream_copy_to_stream($my_file, $encrypted_file);

    fclose($encrypted_file);
    fclose($my_file);
    unlink($temp_file);
Run Code Online (Sandbox Code Playgroud)

temp_file是我可以看到上传文件的第一个实例

dre*_*010 5

如果您尝试像这样大块读取文件,是否会有更好的结果?:

$my_file = fopen($temp_file, 'rb');

$encrypted_file_name = $target_file;
$encrypted_file = fopen($encrypted_file_name, 'wb');

stream_filter_append($encrypted_file, 'mcrypt.rijndael_128', STREAM_FILTER_WRITE, $opts);
//stream_copy_to_stream($my_file, $encrypted_file);

rewind($my_file);

while (!feof($my_file)) {
    fwrite($encrypted_file, fread($my_file, 4096));
}
Run Code Online (Sandbox Code Playgroud)

您也可以尝试在调用stream_set_chunk_size之前先进行调用,stream_copy_to_stream以设置复制到目标时用于从源流读取的缓冲区的大小。

希望能有所帮助。

编辑:我用此代码进行了测试,并且在上载700MB电影文件时,PHP的峰值内存使用量为524,288字节。stream_copy_to_stream除非您通过传递length和offset参数的块将其读取,否则似乎将尝试将整个源文件读取到内存中。

$encrypted_file_name = $target_file;
$encrypted_file = fopen($encrypted_file_name, 'wb');

stream_filter_append($encrypted_file, 'mcrypt.rijndael_128', STREAM_FILTER_WRITE, $opts);

$size = 16777216;  // buffer size of copy
$pos  = 0;         // initial file position

fseek($my_file, 0, SEEK_END);
$length = ftell($my_file);    // get file size

while ($pos < $length) {
    $writ = stream_copy_to_stream($my_file, $encrypted_file, $size, $pos);
    $pos += $writ;
}

fclose($encrypted_file);
fclose($my_file);
unlink($temp_file);
Run Code Online (Sandbox Code Playgroud)

  • @drew010 你的代码非常有帮助,但它对我不起作用,直到我在 while 循环之前添加了 `rewind($my_file);`。 (2认同)
  • fwiw 我在 php7.3 中测试了stream_copy_to_stream 内存使用情况,它使用不到 2MB RAM 来使用 https://paste.debian.net/plain/1276382 复制 1024 GB ram (2认同)