一番下の更新された質問
特定の URL のコンテンツを電子メールに添付して、再度ダウンロードしてアップロードすることなく送信できる PHP スクリプトを作成したいと考えています。
これを行うためのリソースは限られています: PHPと64M のメモリ制限と~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つの部分に分割する必要があります。