Alternative to Stream_Copy_To_Stream() php

喜夏-厌秋 提交于 2021-02-06 11:49:09

问题


I am working on a file sharing site right now and I've run into a small problem. I am using the upload scrip uploadify which works perfectly but if the user wants i want the uploaded file to be encrypted. Now i have working code that does this as shown below but my server only has 1GB or memory and using stream_copy_to_stream seems to take up the size of the actually file in memory and my max upload size is 256 so i know for a fact that something bad is going to happen when the site goes live and multiple people upload large files at once. Based on my code below is there any alternative that barely uses and memory or none at all, I wouldnt even care if it takes longer i just need this to work. I have the download version of this working because i have the file directly decrypted and immediately passed through to the browser so it decrypts as it downloads which i though was pretty efficient but this upload problem doesn't look to good. Any help is appreciated.

$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);

temp_file is the first instance that i can see of the uploaded file


回答1:


Do you have better results if you try reading the file in chunks like this?:

$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));
}

You might also try calling stream_set_chunk_size prior to calling stream_copy_to_stream to set the size of the buffer it uses to read from the source stream when copying to the destination.

Hope that helps.

EDIT: I tested with this code and when uploading a 700MB movie file, the peak memory usage of PHP is 524,288 bytes. It looks like stream_copy_to_stream will try to read the entire source file into memory unless you read it in chunks passing the length and offset arguments.

$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);


来源:https://stackoverflow.com/questions/11679723/alternative-to-stream-copy-to-stream-php

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!