在線轉化.
誰有 把其他的視頻文件格式的視頻,經過上傳自動轉化FLV格式的一種插件.提供編程接口.給我一份.
類似新浪網播客上傳視頻的一樣. (還有上傳是的哪個效果,進度條如何作的?)
或者給我個參考地址什 ...
環境:redhat as4
1。首先獲取ffmpeg
很多人找不到怎么下載,其實之前ffmpeg可以通過cvs下載,不過最近他已經換成了更加強大的svn
如何使用SVN我這里不再介紹,網上還有大量的安裝和使用的文章可以借鑒,這里簡單羅列幾個SVN輔助的軟件:
SubVersion,從 http://subversion.tigris.org/ 下載,支持linux,我們這里就裝這個
TortoiseSVN,從 http://tortoisesvn.tigris.org/ 下載,是很不錯的SVN客戶端程序,為windows外殼程序集成到windows資源管理器和文件管理系統的Subversion客戶端,用起來很方便,commit動作變得就像Winrar右鍵壓縮一樣方便。
ok,那我們先裝subversion,記住最好之前裝過apr和apr-util,在apache.org網站能下到
wget http://subversion.tigris.org/downloads/subversion-1.3.2.tar.gz
tar zvxf subversion-1.3.2.tar.gz
cd subversion-1.3.2
./configure --with-apr=/usr/local/apr-httpd --with-apr-util=/usr/local/apr-util-httpd/
make
make install
到此,我們就可以通過svn命令獲取最新的ffmpeg了
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
你會發現在你所在的目錄,自動出現一個ffmpeg的目錄,就是你下載的源代碼。
我們還不能這么快編譯ffmpeg,應該如果要讓ffmpeg支持更多格式的轉換,還需做一些前期工作
2.支持mp3,linux當然是lame,下載解壓
cd lame-3.96.1
./configure --enable-shared --prefix=/usr
這里推薦盡量裝在/usr下,默認是裝在/usr/local下。這樣ffmpeg編譯都能順利的找到庫文件
3.支持Ogg Vorbis:
as4自帶相應的rpm包,你可以安裝一下如下rpm包
libvorbis, libvorbis-devel,libogg, libogg-devel
4.支持xvid x264,現在最流行的兩種高質量的壓縮格式
xvid的編譯安裝
wget http://downloads.xvid.org/downloads/xvidcore-1.1.0.tar.gz
tar zvxf xvidcore-1.1.0.tar.gz
./configure --prefix=/usr
make
make install
x264的獲取同樣是采用svn方式,看來svn取代cvs不遠了
svn co svn://svn.videolan.org/x264/trunk x264
cd x264
./configure --prefix=/usr --enable-shared
make
make install
5.AC3和dts編碼的支持
as4系統似乎已經支持ac3編碼,編譯的時候只要加--enable-a52 --enable-gpl參數就行
libdts編譯參數
./configure --prefix=/usr
make
make install
6.mpg4 aac格式支持,由于服務器還針對手機用戶服務,所以,類似aac,mpg4鈴聲格式的支持,我們也得做。這里我們安裝faad2和faac就行
下載請到 http://www.audiocoding.com/modules/mydownloads/
FAAD2的編譯
cd faad2
autoreconf -vif
./configure --prefix=/usr --with-mp4v2 --enable-shared
make
make install
faac的編譯
cd faac
chmod +x bootstrap
./bootstrap
./configure --prefix=/usr --with-mp4v2 --enable-shared
make
make install
7.支持3gp格式,這也是現在好多手機支持的格式,因為手機用戶是我們的主要用戶,所以也得支持編譯
編譯的時候加上--enable-amr_nb --enable-amr_wb參數就行,根據編譯系統的提示,所以我們得下載一
些編譯3gp所需得文件。
wget http://www.3gpp.org/ftp/Specs/ar ... 6.204/26204-510.zip
解壓以后把里面的文件都拷貝到libavcodec/amrwb_float
wget http://www.3gpp.org/ftp/Specs/ar ... 6.104/26104-510.zip
解壓以后把里面的文件都拷貝到libavcodec/amr_float
好了,基本ffmpeg支持的格式,我們基本都做好前期準備了,下面是ffmpeg的編譯
./configure --prefix=/usr --enable-gpl --enable-shared --enable-mp3lame --enable-amr_nb --enable-amr_wb --enable-amr_if2 --enable-libogg --enable-vorbis --enable-xvid --enable-a52 --enable-a52bin --enable-faadbin --enable-dts --enable-pp --enable-faad --enable-faac --enable-x264 --enable-pthreads --disable-ffserver --disable-ffplay
make
make install
補充1:
關于3gp的編譯,如果大家要編譯--enable-amr_nb-fixed,那就不能跟--enable-amr_nb同時編譯,我不大清楚這兩者到底有什么區別,似乎fixed是修正版,管他呢,編譯的方法:
wget http://www.3gpp.org/ftp/Specs/ar ... 6.073/26073-510.zip
解壓以后把里面的文件都拷貝到libavcodec/amr目錄下
修改libavcodec/amr/makefile 找到CFLAGS = -Wall -pedantic-errors -I. $(CFLAGS_$(MODE)) -D$(VAD) 換成CFLAGS = -Wall -I. $(CFLAGS_$(MODE)) -D$(VAD) -DMMS_IO
整體編譯參數就是
./configure --prefix=/usr --enable-gpl --enable-shared --enable-mp3lame --enable-amr_nb-fixed --enable-amr_wb --enable-amr_if2 --enable-libogg --enable-vorbis --enable-xvid --enable-a52 --enable-a52bin --enable-dts --enable-pp --enable-faad --enable-faadbin --enable-faac --enable-x264 --enable-pthreads --disable-ffserver --disable-ffplay
make
make install
補充2:
有朋友說在當在cpu是x86的情況下,不能編譯過去,我這里沒發生過這情況,如果你真編譯不過去,可以試著加上cpu=cpu
ok,一個強大的ffmpeg編譯好了,不過目前管方的ffmpeg還不支持wma9和rmvb,不過網上有很多解決方法,大家去自己找找。
================================================
關于進度條的問題,我一直都無法解決.按道理新浪也不可能100%獲取真實進度的吧?如果模擬的話就一大堆了,
我這里提供一UPU的類用的SOCKET協議.
[php]
<?php
/**
* UGiA PHP UPLOADER V0.2
*
* Copyright 2005 legend < legendsky@hotmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* @link http://www.ugia.cn, http://sourceforge.net/projects/upu
* @copyright Copyright: 2004-2005 UGiA.CN.
* @author legend < legendsky@hotmail.com>
* @package UPU
* @version $Id: upu.class.php,v 1.2 2005/09/22 08:03:22 legend9 Exp $
*/
define('UPU_CLIENT_CHARSET', 'utf-8');
define('UPU_TEMP_PATH', '/upload/upu/temp/');
define('UPU_SAVE_PATH', '/upload/upu/files/');
define('UPU_SOCKET_ENDTAG', "/x2d/x2d/x0d/x0a");
define('UPU_CRLF', "/x0d/x0a");
define('UPU_SOCKET_CREATE_ERROR', "Socket創建失敗");
define('UPU_SOCKET_BIND_ERROR', "端口綁定失敗");
define('UPU_SOCKET_LISTEN_ERROR', "端口監聽失敗");
define('UPU_SOKET_ACCEPT_ERROR', "無法接受客戶端請求");
define('UPU_CREATE_TEMP_FILE_ERROR', "創建臨時文件失敗");
define('UPU_FILE_TO_LARGE', "文件超過指定大小");
define('UPU_GET_TMP_FILE_SIZE_ERROR', "獲取臨時文件大小失敗");
define('UPU_READ_TMP_FILE_ERROR', "打開臨時文件失敗");
define('UPU_WRITE_NEW_FILE_ERRPR', "創建新文件失敗");
class UPU
{
var $sPort = 1024;
var $ePort = 65536;
var $savePath = UPU_SAVE_PATH;
var $tmpPath = UPU_TEMP_PATH;
var $allowExt = "*";
var $maxFileSize = 0;
var $srvPort;
var $ipAddr;
var $processID;
var $bufferSize = 1024;
var $Boundary;
var $ContentLength = 0;
var $fileSize = 0;
var $fileInfo = array();
var $formData = array();
var $errorCode = 0;
function UPU ()
{
$this->srvPort = mt_rand($this->sPort, $this->ePort);
$this->ipAddr = $_SERVER['SERVER_NAME'];
}
function processRequest()
{
$uSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($uSocket < 0) return -101;
$uBind = socket_bind($uSocket, $this->ipAddr, $this->srvPort);
if ($uBind < 0) return -102;
//socket_set_blocking($uSocket);
$uListen = socket_listen($uSocket, 5);
if ($uListen < 0) return -103;
$this->writeContents($this->tmpPath . $this->processID . ".srv", $this->ipAddr.":".$this->srvPort);
$uRequest = socket_accept($uSocket);
if ($uRequest < 0) return -104;
$httpResponse = "HTTP/1.1 200 OK/r/n";
$httpResponse .= "Content-Length: 2/r/n";
$httpResponse .= "Content-Type: text/html/r/n";
$httpResponse .= "Last-Modified: " . date("r") . "/r/n";
$httpResponse .= "Accept-Ranges: bytes/r/n";
$httpResponse .= "X-Powered-By: UPU/r/n";
$httpResponse .= "Date: " . date("r") . "/r/n/r/n";
socket_write($uRequest, $httpResponse);
$neededbuffer = true;
$BufferPond = array();
$tmpFileName = $this->tmpPath . $this->processID . ".dat";
if(!$fp = fopen ($tmpFileName, "wb")) return -105;
$dataRead = 0;
while ($flag = socket_recv($uRequest, $buffer, $this->bufferSize, 0))
{
fwrite($fp, $buffer);
// buffer pond
array_push ($BufferPond, $buffer);
if (count($BufferPond) == 3)
{
$dataRead += strlen($BufferPond[0]);
array_shift($BufferPond);
}
$Contents = join("", $BufferPond);
// boundary
if (!$this->Boundary)
{
if (preg_match("/Content-Type: multipart//form-data; boundary=[-]{27}(/S+)/i", $Contents, $matchesB))
$this->Boundary = $matchesB[1];
}
// content length
if (!$this->ContentLength)
{
if (preg_match("/Content-Length: (/d+)/r/n/i", $Contents, $matchesL))
{
$this->ContentLength = $matchesL[1];
$this->writeContents($this->tmpPath . $this->processID . ".con", $this->ContentLength);
if ($this->maxFileSize && $this->ContentLength > $$maxFileSize * 1024 * 1024)
{
return -106;
break;
}
}
}
// parse
$boundary = str_repeat("-", 29) . $this->Boundary;
if (strpos($Contents, $boundary))
{
preg_match_all("/$boundary/r/nContent-Disposition: form-data; name=/"([^/"]*)/"(; filename=/"([^/"]*)/"/r/nContent-Type: (/S+))?/r/n/i", $Contents, $matchesF, PREG_OFFSET_CAPTURE);
//print_r($matchesF);
if ($matchesF)
{
for ($i = 0; $i < count($matchesF[0]); $i ++)
{
$formIndex = $this->checkFormName($matchesF[1][$i][0], $this->formData);
if ( $formIndex === -1)
{
$this->formData[] = array (
'name' => $matchesF[1][$i][0],
'type' => $matchesF[3][$i] ? "file" : "form",
'filename' => $matchesF[3][$i][0],
'content-type' => $matchesF[4][$i][0],
'offset' => $dataRead + $matchesF[0][$i][1],
'full' => $matchesF[0][$i][0]
);
if ($matchesF[3][$i])
{
$clientArray = "new Array(/"" . $matchesF[1][$i][0] . "/",/"" . $this->getBaseName($matchesF[3][$i][0]) . "/",/"" . $matchesF[4][$i][0] . "/")";
$this->writeContents($this->tmpPath . $this->processID . ".inf", $clientArray);
}
}
}
}
else
{
break;
}
}
if ($flag < 0)
{
echo socket_strerror(socket_last_error($uSocket));
break;
}
elseif ($flag == 0)
{
echo "client disconnected";
break;
}
// end of request ?
$eof = substr($buffer, -4);
$las = substr($buffer, $this->bufferSize - 4, 4);
if ($eof == UPU_SOCKET_ENDTAG || (strlen($eof) < 4 && ($las{strlen($eof) -1} == "/x0a" || $las{strlen($eof) -1} == "/x00")))
{
break;
}
$loopTime ++;
}
fclose($fp);
$msg = "ok";
socket_write($uRequest, $msg, strlen($msg));
socket_close($uRequest);
socket_close($uSocket);
//print_r($this->fileInfo);
//print_r($this->formData);
// temp file size
if (!$this->fileSize = @filesize($tmpFileName))
{
return -108;
}
// temp file read handle
if (!$readHandle = fopen($tmpFileName, "rb"))
{
return -109;
}
foreach ($this->formData as $k => $v)
{
fseek($readHandle, $v['offset'] + strlen($v['full']) + 2);
$eOffset = $k + 1 == count($this->formData)? $this->fileSize - 35 - strlen($this->Boundary) : $this->formData[$k + 1]['offset'] - 2;
$this->formData[$k]['filesize'] = $eOffset - $v['offset'] - strlen($v['full']) - 2;
if ($v['type'] == "file")
{
$extension = $this->getExtension($v['filename']);
$savepath = $this->savePath . md5($this->processID . "-" . $k) . "." . $extension;
$writeHandle = fopen($savepath, "wb");
fwrite($writeHandle, @fread($readHandle,$this->formData[$k]['filesize']));
fclose($writeHandle);
$this->formData[$k]['ext'] = $extension;
$this->formData[$k]['path'] = $savepath;
}
else
{
$this->formData[$k]['value'] = @fread($readHandle, $this->formData[$k]['filesize']);
}
}
fclose($readHandle);
$form = array();
foreach ($this->formData as $k => $v)
{
if ($v['type'] == "file")
{
$form[$v['name']] = array(
'filename' => $this->getBaseName($v['filename']),
'extension' => $v['ext'],
'clientpath' => $v['filename'],
'savepath' => realpath($v['path']),
'filetype' => $v['content-type'],
'filesize' => $v['filesize'],
'extension' => $v['ext']
);
}
else
{
$form[$v['name']] = $v['value'];
}
}
$this->writeContents($this->tmpPath . $this->processID . ".frm", serialize($form));
sleep(60);
unlink($this->tmpPath . $this->processID . ".inf");
unlink($this->tmpPath . $this->processID . ".dat");
unlink($this->tmpPath . $this->processID . ".con");
unlink($this->tmpPath . $this->processID . ".srv");
}
// get socket server ip address and port
function getSrvAddr()
{
return $this->getContents($this->tmpPath . $this->processID . ".srv");
}
// get Content Length
function getContentLength()
{
return $this->getContents($this->tmpPath . $this->processID . ".con");
}
// get file info
function getFileInfo()
{
return $this->getContents($this->tmpPath . $this->processID . ".inf");
}
// get uploaded file length
function getUploadedLength()
{
if (file_exists($this->tmpPath . $this->processID . ".dat"))
{
return filesize($this->tmpPath . $this->processID . ".dat");
}
return 0;
}
function getFormData()
{
if (file_exists($this->tmpPath . $this->processID . ".frm"))
{
return $this->getContents($this->tmpPath . $this->processID . ".frm");
}
return 0;
}
function writeContents($filename, $contents)
{
$fwriteHandle = @fopen($filename, "w");
if (!is_resource($fwriteHandle))
{
return false;
}
fwrite($fwriteHandle, $contents);
fclose($fwriteHandle);
return true;
}
function getContents($filename)
{
if (file_exists($filename))
{
$freadHandle = @fopen($filename, "r");
if (!is_resource($freadHandle))
{
return false;
}
$contents = fread($freadHandle, filesize($filename));
fclose($freadHandle);
return $contents;
}
return false;
}
function getBaseName($path)
{
$path = str_replace("//", "/", $path);
return substr($path, strrpos($path, "/") + 1);
}
function getExtension($filename)
{
return substr(strrchr($filename, '.'), 1);
}
function checkFormName($formName, $arr)
{
foreach ($arr as $k => $v)
{
if ($formName == $v['name'])
{
return $k;
}
}
return -1;
}
}
?>?
誰有 把其他的視頻文件格式的視頻,經過上傳自動轉化FLV格式的一種插件.提供編程接口.給我一份.
類似新浪網播客上傳視頻的一樣. (還有上傳是的哪個效果,進度條如何作的?)
或者給我個參考地址什 ...
環境:redhat as4
1。首先獲取ffmpeg
很多人找不到怎么下載,其實之前ffmpeg可以通過cvs下載,不過最近他已經換成了更加強大的svn
如何使用SVN我這里不再介紹,網上還有大量的安裝和使用的文章可以借鑒,這里簡單羅列幾個SVN輔助的軟件:
SubVersion,從 http://subversion.tigris.org/ 下載,支持linux,我們這里就裝這個
TortoiseSVN,從 http://tortoisesvn.tigris.org/ 下載,是很不錯的SVN客戶端程序,為windows外殼程序集成到windows資源管理器和文件管理系統的Subversion客戶端,用起來很方便,commit動作變得就像Winrar右鍵壓縮一樣方便。
ok,那我們先裝subversion,記住最好之前裝過apr和apr-util,在apache.org網站能下到
wget http://subversion.tigris.org/downloads/subversion-1.3.2.tar.gz
tar zvxf subversion-1.3.2.tar.gz
cd subversion-1.3.2
./configure --with-apr=/usr/local/apr-httpd --with-apr-util=/usr/local/apr-util-httpd/
make
make install
到此,我們就可以通過svn命令獲取最新的ffmpeg了
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
你會發現在你所在的目錄,自動出現一個ffmpeg的目錄,就是你下載的源代碼。
我們還不能這么快編譯ffmpeg,應該如果要讓ffmpeg支持更多格式的轉換,還需做一些前期工作
2.支持mp3,linux當然是lame,下載解壓
cd lame-3.96.1
./configure --enable-shared --prefix=/usr
這里推薦盡量裝在/usr下,默認是裝在/usr/local下。這樣ffmpeg編譯都能順利的找到庫文件
3.支持Ogg Vorbis:
as4自帶相應的rpm包,你可以安裝一下如下rpm包
libvorbis, libvorbis-devel,libogg, libogg-devel
4.支持xvid x264,現在最流行的兩種高質量的壓縮格式
xvid的編譯安裝
wget http://downloads.xvid.org/downloads/xvidcore-1.1.0.tar.gz
tar zvxf xvidcore-1.1.0.tar.gz
./configure --prefix=/usr
make
make install
x264的獲取同樣是采用svn方式,看來svn取代cvs不遠了
svn co svn://svn.videolan.org/x264/trunk x264
cd x264
./configure --prefix=/usr --enable-shared
make
make install
5.AC3和dts編碼的支持
as4系統似乎已經支持ac3編碼,編譯的時候只要加--enable-a52 --enable-gpl參數就行
libdts編譯參數
./configure --prefix=/usr
make
make install
6.mpg4 aac格式支持,由于服務器還針對手機用戶服務,所以,類似aac,mpg4鈴聲格式的支持,我們也得做。這里我們安裝faad2和faac就行
下載請到 http://www.audiocoding.com/modules/mydownloads/
FAAD2的編譯
cd faad2
autoreconf -vif
./configure --prefix=/usr --with-mp4v2 --enable-shared
make
make install
faac的編譯
cd faac
chmod +x bootstrap
./bootstrap
./configure --prefix=/usr --with-mp4v2 --enable-shared
make
make install
7.支持3gp格式,這也是現在好多手機支持的格式,因為手機用戶是我們的主要用戶,所以也得支持編譯
編譯的時候加上--enable-amr_nb --enable-amr_wb參數就行,根據編譯系統的提示,所以我們得下載一
些編譯3gp所需得文件。
wget http://www.3gpp.org/ftp/Specs/ar ... 6.204/26204-510.zip
解壓以后把里面的文件都拷貝到libavcodec/amrwb_float
wget http://www.3gpp.org/ftp/Specs/ar ... 6.104/26104-510.zip
解壓以后把里面的文件都拷貝到libavcodec/amr_float
好了,基本ffmpeg支持的格式,我們基本都做好前期準備了,下面是ffmpeg的編譯
./configure --prefix=/usr --enable-gpl --enable-shared --enable-mp3lame --enable-amr_nb --enable-amr_wb --enable-amr_if2 --enable-libogg --enable-vorbis --enable-xvid --enable-a52 --enable-a52bin --enable-faadbin --enable-dts --enable-pp --enable-faad --enable-faac --enable-x264 --enable-pthreads --disable-ffserver --disable-ffplay
make
make install
補充1:
關于3gp的編譯,如果大家要編譯--enable-amr_nb-fixed,那就不能跟--enable-amr_nb同時編譯,我不大清楚這兩者到底有什么區別,似乎fixed是修正版,管他呢,編譯的方法:
wget http://www.3gpp.org/ftp/Specs/ar ... 6.073/26073-510.zip
解壓以后把里面的文件都拷貝到libavcodec/amr目錄下
修改libavcodec/amr/makefile 找到CFLAGS = -Wall -pedantic-errors -I. $(CFLAGS_$(MODE)) -D$(VAD) 換成CFLAGS = -Wall -I. $(CFLAGS_$(MODE)) -D$(VAD) -DMMS_IO
整體編譯參數就是
./configure --prefix=/usr --enable-gpl --enable-shared --enable-mp3lame --enable-amr_nb-fixed --enable-amr_wb --enable-amr_if2 --enable-libogg --enable-vorbis --enable-xvid --enable-a52 --enable-a52bin --enable-dts --enable-pp --enable-faad --enable-faadbin --enable-faac --enable-x264 --enable-pthreads --disable-ffserver --disable-ffplay
make
make install
補充2:
有朋友說在當在cpu是x86的情況下,不能編譯過去,我這里沒發生過這情況,如果你真編譯不過去,可以試著加上cpu=cpu
ok,一個強大的ffmpeg編譯好了,不過目前管方的ffmpeg還不支持wma9和rmvb,不過網上有很多解決方法,大家去自己找找。
================================================
關于進度條的問題,我一直都無法解決.按道理新浪也不可能100%獲取真實進度的吧?如果模擬的話就一大堆了,
我這里提供一UPU的類用的SOCKET協議.
[php]
<?php
/**
* UGiA PHP UPLOADER V0.2
*
* Copyright 2005 legend < legendsky@hotmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* @link http://www.ugia.cn, http://sourceforge.net/projects/upu
* @copyright Copyright: 2004-2005 UGiA.CN.
* @author legend < legendsky@hotmail.com>
* @package UPU
* @version $Id: upu.class.php,v 1.2 2005/09/22 08:03:22 legend9 Exp $
*/
define('UPU_CLIENT_CHARSET', 'utf-8');
define('UPU_TEMP_PATH', '/upload/upu/temp/');
define('UPU_SAVE_PATH', '/upload/upu/files/');
define('UPU_SOCKET_ENDTAG', "/x2d/x2d/x0d/x0a");
define('UPU_CRLF', "/x0d/x0a");
define('UPU_SOCKET_CREATE_ERROR', "Socket創建失敗");
define('UPU_SOCKET_BIND_ERROR', "端口綁定失敗");
define('UPU_SOCKET_LISTEN_ERROR', "端口監聽失敗");
define('UPU_SOKET_ACCEPT_ERROR', "無法接受客戶端請求");
define('UPU_CREATE_TEMP_FILE_ERROR', "創建臨時文件失敗");
define('UPU_FILE_TO_LARGE', "文件超過指定大小");
define('UPU_GET_TMP_FILE_SIZE_ERROR', "獲取臨時文件大小失敗");
define('UPU_READ_TMP_FILE_ERROR', "打開臨時文件失敗");
define('UPU_WRITE_NEW_FILE_ERRPR', "創建新文件失敗");
class UPU
{
var $sPort = 1024;
var $ePort = 65536;
var $savePath = UPU_SAVE_PATH;
var $tmpPath = UPU_TEMP_PATH;
var $allowExt = "*";
var $maxFileSize = 0;
var $srvPort;
var $ipAddr;
var $processID;
var $bufferSize = 1024;
var $Boundary;
var $ContentLength = 0;
var $fileSize = 0;
var $fileInfo = array();
var $formData = array();
var $errorCode = 0;
function UPU ()
{
$this->srvPort = mt_rand($this->sPort, $this->ePort);
$this->ipAddr = $_SERVER['SERVER_NAME'];
}
function processRequest()
{
$uSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($uSocket < 0) return -101;
$uBind = socket_bind($uSocket, $this->ipAddr, $this->srvPort);
if ($uBind < 0) return -102;
//socket_set_blocking($uSocket);
$uListen = socket_listen($uSocket, 5);
if ($uListen < 0) return -103;
$this->writeContents($this->tmpPath . $this->processID . ".srv", $this->ipAddr.":".$this->srvPort);
$uRequest = socket_accept($uSocket);
if ($uRequest < 0) return -104;
$httpResponse = "HTTP/1.1 200 OK/r/n";
$httpResponse .= "Content-Length: 2/r/n";
$httpResponse .= "Content-Type: text/html/r/n";
$httpResponse .= "Last-Modified: " . date("r") . "/r/n";
$httpResponse .= "Accept-Ranges: bytes/r/n";
$httpResponse .= "X-Powered-By: UPU/r/n";
$httpResponse .= "Date: " . date("r") . "/r/n/r/n";
socket_write($uRequest, $httpResponse);
$neededbuffer = true;
$BufferPond = array();
$tmpFileName = $this->tmpPath . $this->processID . ".dat";
if(!$fp = fopen ($tmpFileName, "wb")) return -105;
$dataRead = 0;
while ($flag = socket_recv($uRequest, $buffer, $this->bufferSize, 0))
{
fwrite($fp, $buffer);
// buffer pond
array_push ($BufferPond, $buffer);
if (count($BufferPond) == 3)
{
$dataRead += strlen($BufferPond[0]);
array_shift($BufferPond);
}
$Contents = join("", $BufferPond);
// boundary
if (!$this->Boundary)
{
if (preg_match("/Content-Type: multipart//form-data; boundary=[-]{27}(/S+)/i", $Contents, $matchesB))
$this->Boundary = $matchesB[1];
}
// content length
if (!$this->ContentLength)
{
if (preg_match("/Content-Length: (/d+)/r/n/i", $Contents, $matchesL))
{
$this->ContentLength = $matchesL[1];
$this->writeContents($this->tmpPath . $this->processID . ".con", $this->ContentLength);
if ($this->maxFileSize && $this->ContentLength > $$maxFileSize * 1024 * 1024)
{
return -106;
break;
}
}
}
// parse
$boundary = str_repeat("-", 29) . $this->Boundary;
if (strpos($Contents, $boundary))
{
preg_match_all("/$boundary/r/nContent-Disposition: form-data; name=/"([^/"]*)/"(; filename=/"([^/"]*)/"/r/nContent-Type: (/S+))?/r/n/i", $Contents, $matchesF, PREG_OFFSET_CAPTURE);
//print_r($matchesF);
if ($matchesF)
{
for ($i = 0; $i < count($matchesF[0]); $i ++)
{
$formIndex = $this->checkFormName($matchesF[1][$i][0], $this->formData);
if ( $formIndex === -1)
{
$this->formData[] = array (
'name' => $matchesF[1][$i][0],
'type' => $matchesF[3][$i] ? "file" : "form",
'filename' => $matchesF[3][$i][0],
'content-type' => $matchesF[4][$i][0],
'offset' => $dataRead + $matchesF[0][$i][1],
'full' => $matchesF[0][$i][0]
);
if ($matchesF[3][$i])
{
$clientArray = "new Array(/"" . $matchesF[1][$i][0] . "/",/"" . $this->getBaseName($matchesF[3][$i][0]) . "/",/"" . $matchesF[4][$i][0] . "/")";
$this->writeContents($this->tmpPath . $this->processID . ".inf", $clientArray);
}
}
}
}
else
{
break;
}
}
if ($flag < 0)
{
echo socket_strerror(socket_last_error($uSocket));
break;
}
elseif ($flag == 0)
{
echo "client disconnected";
break;
}
// end of request ?
$eof = substr($buffer, -4);
$las = substr($buffer, $this->bufferSize - 4, 4);
if ($eof == UPU_SOCKET_ENDTAG || (strlen($eof) < 4 && ($las{strlen($eof) -1} == "/x0a" || $las{strlen($eof) -1} == "/x00")))
{
break;
}
$loopTime ++;
}
fclose($fp);
$msg = "ok";
socket_write($uRequest, $msg, strlen($msg));
socket_close($uRequest);
socket_close($uSocket);
//print_r($this->fileInfo);
//print_r($this->formData);
// temp file size
if (!$this->fileSize = @filesize($tmpFileName))
{
return -108;
}
// temp file read handle
if (!$readHandle = fopen($tmpFileName, "rb"))
{
return -109;
}
foreach ($this->formData as $k => $v)
{
fseek($readHandle, $v['offset'] + strlen($v['full']) + 2);
$eOffset = $k + 1 == count($this->formData)? $this->fileSize - 35 - strlen($this->Boundary) : $this->formData[$k + 1]['offset'] - 2;
$this->formData[$k]['filesize'] = $eOffset - $v['offset'] - strlen($v['full']) - 2;
if ($v['type'] == "file")
{
$extension = $this->getExtension($v['filename']);
$savepath = $this->savePath . md5($this->processID . "-" . $k) . "." . $extension;
$writeHandle = fopen($savepath, "wb");
fwrite($writeHandle, @fread($readHandle,$this->formData[$k]['filesize']));
fclose($writeHandle);
$this->formData[$k]['ext'] = $extension;
$this->formData[$k]['path'] = $savepath;
}
else
{
$this->formData[$k]['value'] = @fread($readHandle, $this->formData[$k]['filesize']);
}
}
fclose($readHandle);
$form = array();
foreach ($this->formData as $k => $v)
{
if ($v['type'] == "file")
{
$form[$v['name']] = array(
'filename' => $this->getBaseName($v['filename']),
'extension' => $v['ext'],
'clientpath' => $v['filename'],
'savepath' => realpath($v['path']),
'filetype' => $v['content-type'],
'filesize' => $v['filesize'],
'extension' => $v['ext']
);
}
else
{
$form[$v['name']] = $v['value'];
}
}
$this->writeContents($this->tmpPath . $this->processID . ".frm", serialize($form));
sleep(60);
unlink($this->tmpPath . $this->processID . ".inf");
unlink($this->tmpPath . $this->processID . ".dat");
unlink($this->tmpPath . $this->processID . ".con");
unlink($this->tmpPath . $this->processID . ".srv");
}
// get socket server ip address and port
function getSrvAddr()
{
return $this->getContents($this->tmpPath . $this->processID . ".srv");
}
// get Content Length
function getContentLength()
{
return $this->getContents($this->tmpPath . $this->processID . ".con");
}
// get file info
function getFileInfo()
{
return $this->getContents($this->tmpPath . $this->processID . ".inf");
}
// get uploaded file length
function getUploadedLength()
{
if (file_exists($this->tmpPath . $this->processID . ".dat"))
{
return filesize($this->tmpPath . $this->processID . ".dat");
}
return 0;
}
function getFormData()
{
if (file_exists($this->tmpPath . $this->processID . ".frm"))
{
return $this->getContents($this->tmpPath . $this->processID . ".frm");
}
return 0;
}
function writeContents($filename, $contents)
{
$fwriteHandle = @fopen($filename, "w");
if (!is_resource($fwriteHandle))
{
return false;
}
fwrite($fwriteHandle, $contents);
fclose($fwriteHandle);
return true;
}
function getContents($filename)
{
if (file_exists($filename))
{
$freadHandle = @fopen($filename, "r");
if (!is_resource($freadHandle))
{
return false;
}
$contents = fread($freadHandle, filesize($filename));
fclose($freadHandle);
return $contents;
}
return false;
}
function getBaseName($path)
{
$path = str_replace("//", "/", $path);
return substr($path, strrpos($path, "/") + 1);
}
function getExtension($filename)
{
return substr(strrchr($filename, '.'), 1);
}
function checkFormName($formName, $arr)
{
foreach ($arr as $k => $v)
{
if ($formName == $v['name'])
{
return $k;
}
}
return -1;
}
}
?>?