2013-04-05 1 views
0

Udated вопрос в нижнейPHP: данный URL-адрес для отправки по электронной почте в виде вложения (без загрузки)?

Я хочу написать PHP скрипт ведьму может отправить содержание данного URL прилагается к электронной почте без скачивания и загрузки снова.

Я ограниченные ресурсы, чтобы сделать это: нормальный хостинг счета с PHP и 64M ограничение по памяти и ~ 1ГБ

Мой первый код был простой 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="[email protected]"; // 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 bytes Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 66846720 bytes) in /url2mail.php on line 58 the line 58 is: $file = file_get_contents($file_url);

ОБНОВЛЕНИЕ рабочая версия наклеены ниже, но все еще ограничена в максимизируется разрешенной памяти. Мне нравится делать Базовые 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="[email protected]".$_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 части.

+0

Так вы на самом деле пытались осуществить это на всех или, по крайней мере, есть какие-либо мысли о том, как вы могли бы идти об этом? –

+0

Да, я пробовал, но я не хочу вставлять код здесь, потому что надеюсь на совершенно другое решение. Но я вставляю свой код сейчас, чтобы быть понятным. – eapo

+0

Я предпочитаю исправление и обучение, а не нисходящее. Спасибо! – eapo

ответ

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-s к вашей БД таблицы или файла CSV, и ждать писем ,

+0

отлично, я надеюсь, что есть решение без сохранения файлов на сервер. – eapo

1

Эта функция может сделать задачу:

function mail_page_contents($url = '') 
{ 
    if($url && ($contents = file_get_contents($url))) 
    { 
     $emailto = '[email protected]'; 

     $subject = 'Webpage Contents'; 

     mail($emailto , $subject , $contents); 
    } 
} 
Смежные вопросы