0

一番下の更新された質問

特定の URL のコンテンツを電子メールに添付して、再度ダウンロードしてアップロードすることなく送信できる PHP スクリプトを作成したいと考えています。

これを行うためのリソースは限られています: PHP64M のメモリ制限~1GB のストレージを備えた通常のホスティング アカウント

私の最初のコードは を使用した単純な sendmail でしたがfopen()、指定されたファイルが大きすぎるとメモリの問題が発生します。どうすればこれを修正できますか?

<?php
// return the file size of remote file
function ffilesize($remoteFile,$verbose=0){
    $ch = curl_init($remoteFile);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
    $data = curl_exec($ch);
    curl_close($ch);
    if ($data === false) {
      echo 'cURL failed';
      exit;
    }

    $contentLength = 'unknown';
    $status = 'unknown';
    if (preg_match('/^HTTP\/1\.[01] (\d\d\d)/', $data, $matches)) {
      $status = (int)$matches[1];
    }
    if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
      $contentLength = (int)$matches[1];
    }
    return ($verbose)?number_format($contentLength)." bytes":$contentLength;
}

$file_url=$_GET['q']; // the given URL

print ffilesize($file_url,1); // check the file size of given URL

if ($_GET['m']) { // allow to send mail
    $filesize=ffilesize($file_url);
    $to=$_GET['to']; // For the file to be sent.
    $from="no-reply@domain.com"; // For the from line on the received email
    $name=$_GET['fname']; // virtual name of attached file
    $type="application/x-gzip";
                $subject = "subj";
                $mime_boundary = "==Multipart_Boundary_x".md5(mt_rand())."x";
             // open the file for a binary read
                $file = file_get_contents($file_url);
             // read the file content into a variable
                $data = chunk_split(base64_encode(file_get_contents($file_url)));
             // now we encode it and split it into acceptable length lines
                //ALREADY DONE, MOVE UP A FEW LINES
             // message body
                $message = "file attached";
             // build headers
                $headers = "Content-Type: multipart/mixed;\r\n" .
                " boundary=\"{$mime_boundary}\"";
             // put message body in mime boundries
                $message = "This is a multi-part message in MIME format.\n\n" .
                "--{$mime_boundary}\n" .
                "Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
                "Content-Transfer-Encoding: 7bit\n\n" .
                $message . "\n\n";
             // attachment with mime babble
                 $message .= "--{$mime_boundary}\n" .
                "Content-Type: {$type};\n" .
                " name=\"{$name}\"\n" .
                //"Content-Disposition: attachment;\n" .
                //" filename=\"{$backfile}\"\n" .
                "Content-Transfer-Encoding: base64\n\n" .
                $data . "\n\n" .
                "--{$mime_boundary}--\n";
             // send mail
                mail($to, $subject, $message, $headers);
}
?>

この方法の問題:

73,214,655 バイト致命的なエラー: 行 58 の /url2mail.php で 67108864 バイトの許容メモリ サイズが使い果たされました (66846720 バイトを割り当てようとしました)。行 58は次のとおりです。$file = file_get_contents($file_url);

更新 以下に貼り付けられた作業バージョンですが、最大化された許容メモリによってまだ制限されています。サーバーにファイルをダウンロードする代わりに、Base 64 でエンコードされたスライスをメモリに作成するのが大好きです。

<html><head><title></title>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
</head><body bgcolor="#000000" color="#00ff00" style="padding: 3em;margin: 0;color: #00ff00;">
<pre><?php

if(preg_match("/ ***my top secret user agent string*** /i",$_SERVER['HTTP_USER_AGENT'])){
// security check    
    $mem=($_GET['M'])?$_GET['M']:'32M'; // change memory limit if needed
    ini_set('memory_limit', $mem);

    function ffilesize($remoteFile,$verbose=0){ // return the file size of remote file
        $ch = curl_init($remoteFile);
        curl_setopt($ch, CURLOPT_NOBODY, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
        $data = curl_exec($ch);
        curl_close($ch);
        if ($data === false) {
          echo 'cURL failed';
          exit;
        }

        $contentLength = 'unknown';
        $status = 'unknown';
        if (preg_match('/^HTTP\/1\.[01] (\d\d\d)/', $data, $matches)) {
          $status = (int)$matches[1];
        }
        if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
          $contentLength = (int)$matches[1];
        }

        return ($verbose)?number_format($contentLength)." bytes":$contentLength;
    }

    $furl=$_GET['q'];  // the given URL
    $fname=pathinfo(parse_url($furl, PHP_URL_PATH), PATHINFO_BASENAME); // name of given file

    function return_bytes($val) {  // convert size to bytes
        $val = trim($val);
        $last = strtolower($val[strlen($val)-1]);
        switch($last) {
            // The 'G' modifier is available since PHP 5.1.0
            case 'g':
                $val *= 1024;
            case 'm':
                $val *= 1024;
            case 'k':
                $val *= 1024;
        }
        return $val;
    }

    function mem($c=FALSE){  // checking allowed memory and used memory
        $limit=return_bytes(ini_get('memory_limit'));
        if ($c) {
            return $limit - (memory_get_usage()*$c);
    } else {
            return $limit - memory_get_usage();
        }
    }

    $filesize=(file_exists($fname))?filesize($furl):ffilesize($furl);

    echo "<br /> file: ".number_format($filesize);  // debug formatted file size
    echo "<br /> mfree: ".number_format(mem());  // debug free memory
    echo "<br /> mopt: ".number_format(mem(6));  // debug optimal memory usage

    if($filesize>(mem())){  // debug file size information
        echo "<br /> [".$filesize."] too large <br />";
    } else {
        echo "<br /> [".$filesize."] is cool <br />";
    }

    if ($_GET['to']) {  // allow to send email
        if (function_exists('curl_init')&&!file_exists($fname)) {  // downloading the file
            $ch = curl_init($furl);
            $fh = fopen($fname, "w");
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0');
            curl_setopt($ch, CURLOPT_FILE, $fh);
            curl_exec($ch);
            curl_close($ch);
        } else {
            echo 'file existing on server';
        }

        $furl = $fname;  // redeclare the $furl to local

        $to=$_GET['to']."@gmail.com"; // For the file to be sent.
        $from="no-reply@".$_SERVER['SERVER_NAME']; // For the from line on the received email
        $name="asd.gif"; // virtual name .gif for content protection
        $type="application/x-gzip";
           $subject = "subj";
           $mime_boundary = "==Multipart_Boundary_x".md5($rand)."x";
        // open the file for a binary read
           $file = fopen($furl,'rb');
        // read the file content into a variable and encode it and split it into acceptable length lines
           $data = chunk_split(base64_encode(fread($file,$filesize)));
        // message body
           $message = $furl." (".number_format(filesize($furl)).")";
        // build headers
           $headers = "Content-Type: multipart/mixed;\r\n" .
           " boundary=\"{$mime_boundary}\"";
        // put message body in mime boundries
           $message = "This is a multi-part message in MIME format.\n\n" .
           "--{$mime_boundary}\n" .
           "Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
           "Content-Transfer-Encoding: 7bit\n\n" .
           $message . "\n\n";
        // attachment with mime babble
            $message .= "--{$mime_boundary}\n" .
           "Content-Type: {$type};\n" .
           " name=\"{$name}\"\n" .
           "Content-Transfer-Encoding: base64\n\n" .
           $data . "\n\n" .
           "--{$mime_boundary}--\n";
        // close the file
        fclose($file);
        // send mail
        if (mail($to, $subject, $message, $headers)) {
            echo " done";
            unlink($furl);
        } else {
            echo $furl;
        }
    }
} else {
    echo "unauthorized request";
}
?></body></html>

したがって、私の質問は次のとおりです。指定されたファイルを (URL によって) メモリ制限で許可されているスライスに分割するにはどうすればよいですか?

例:32Mのメモリ制限により、メモリに最大30Mを保存できるため、 30Mのファイルを3つの部分に分割する必要があります。

4

2 に答える 2

1

この関数は次のタスクを実行できます。

function mail_page_contents( $url = '' )
{
    if( $url && ( $contents = file_get_contents( $url ) ) )
    {
        $emailto    = 'receiver@email.com';

        $subject    = 'Webpage Contents';

        mail( $emailto , $subject , $contents );
    }
}
于 2013-04-05T15:49:10.737 に答える
0

次の手順を実行します。

1) a) Store url-s in a `mysql` table 
   b) if you does not have mysql than store the urls in a `csv` file.

2) - Php reads the urls 
       a) from the table (with `mysqli` php lib)
       b) with `fgetcsv` function
   - and dowload the content of the url with `curl`
   - zip the content with `ZipArchive` class. /if you want to use less space and bandwith/
   - Send the zipped content as attached file with `PHPMailer`

3) The 2) should run over the urls (and somehow flag what url-s are examined) 
     (if the runtime of the script reaches MAX_EXECUTION_TIME it is stops. 
      So if the script run again, it should start where it is ended at last run)

4) Setup a `cron` job to call your script as often as you need. 

このようにスクリプトを作成すると、URL を db テーブルまたは csv ファイルに追加してメールを待つだけで済みます。

于 2013-04-05T15:48:08.970 に答える