php文件上傳代碼Html中表單不能實(shí)現(xiàn)文件的上傳,限制了一些網(wǎng)頁功能 php文件域上傳
2022-05-01
以前的Html,表單無法實(shí)現(xiàn)文件的上傳,這在一定程度上限制了一些網(wǎng)頁的功能。規(guī)范(即在 Html 中實(shí)現(xiàn)基于表單的文件上傳)通過添加表單元素
<="POST" ="*.jsp" ="/form-data">
<TYPE="FILE" SIZE="50"><BR>
<TYPE="" ="">
選擇粘貼文件時(shí),直接輸入本地文件的絕對路徑。表單的屬性值為*.jsp,表示請求(包括上傳的文件)會被發(fā)送到*..jsp文件。在這個(gè)過程中,實(shí)際上實(shí)現(xiàn)了文件上傳的HTTP方式。 HTTP 協(xié)議的通用網(wǎng)關(guān)接口 (CGI) 支持從客戶端向服務(wù)器上傳文件。這種上傳方式需要瀏覽器和雙方都能夠支持。通過類的()方法獲取客戶端發(fā)給服務(wù)器的一個(gè)數(shù)據(jù)流,分析上傳的文件格式,根據(jù)分析結(jié)果依次輸出多個(gè)文件到服務(wù)器端的目標(biāo)文件。本例中的功能由類具體實(shí)現(xiàn)。該類的框架如下:
{
(){…}
無效()
{ = .(); }
無效(),,,
{………}
void(){………}
void(){………}
int save()
, ,
{………}
……
}
由 () 方法初始化的運(yùn)行時(shí)環(huán)境。使用()方法獲取輸入流,分析上傳文件的格式,將每個(gè)上傳文件的屬性分配給多個(gè)File類實(shí)例進(jìn)行處理。這些 File 類實(shí)例由類管理。 File類根據(jù)每個(gè)文件的屬性調(diào)用其save()方法,將多個(gè)文件依次輸出到服務(wù)器端的目標(biāo)文件中。 ()方法是關(guān)鍵,用于分析.1協(xié)議傳輸?shù)奈募袷?。?jīng)過測試,我們想出了傳輸流文件的格式,這對理解()方法很有用。例如,上傳我的\tt.txt 文件。格式如下:
//文件分隔符
------------------
//文件頭
-: 表單數(shù)據(jù);; ="C:\ 和 \.-\我的 \tt.sql"
-類型:文本/
//源文件內(nèi)容
信息(
null);
//下一個(gè)文件的分隔符
------------------
-: 表單數(shù)據(jù);; =""
-類型:/-
------------------
從以上文件我們可以看出,HTTP協(xié)議在上傳多個(gè)文件時(shí),會將所有文件放入輸入流中,并用一定的分隔符進(jìn)行區(qū)分。其實(shí)()方法就是對上面的文件進(jìn)行分析,確定分隔符的內(nèi)容,每個(gè)文件的內(nèi)容格式,文件的全路徑名,以及文件實(shí)際數(shù)據(jù)的開頭和結(jié)尾。這里需要注意的是,分隔符是隨機(jī)的,是傳輸流文件第一個(gè)回車之前的所有字符。
實(shí)施過程
()方法是:首先將輸入流文件輸出到字節(jié)數(shù)組中,由以下代碼實(shí)現(xiàn)。
=1024;=0;
for(; < ; += )
試試
{ .();
= .().read(, , - );
}(e){ new (" to .");}
這里使用了循環(huán)中的多字節(jié)讀取方式,上面的循環(huán)繼續(xù)讀取數(shù)據(jù),直到數(shù)組滿為止。如果文件完全可用,則文件的所有字節(jié)都可用。但是由于網(wǎng)絡(luò)速度通常比 CPU 慢很多,所以程序很容易在所有數(shù)據(jù)到達(dá)之前清空網(wǎng)絡(luò)緩沖區(qū)。實(shí)際上,當(dāng)多字節(jié)讀取方法嘗試從一個(gè)暫時(shí)空但打開的網(wǎng)絡(luò)緩沖區(qū)中讀取數(shù)據(jù)時(shí),該方法返回0,這意味著沒有數(shù)據(jù)存在但網(wǎng)絡(luò)流沒有關(guān)閉。在這種情況下,單字節(jié)方法會阻塞正在運(yùn)行的程序的執(zhí)行,所以多字節(jié)的行為要優(yōu)于單字節(jié)的 read() 方法。接下來分析字節(jié)數(shù)組。首先找到分隔符;使用()方法返回文件信息頭的值,從中確定源文件的全路徑名、源文件的擴(kuò)展名和源文件的內(nèi)容格式;使用()方法返回文件的內(nèi)容數(shù)據(jù),并記錄文件數(shù)據(jù)在字節(jié)數(shù)組中的開始和結(jié)束位置。然后生成一個(gè)File類的實(shí)例,并將文件的全路徑名、源文件的擴(kuò)展名、源文件的內(nèi)容格式、文件內(nèi)容數(shù)據(jù)的起止位置放入屬性中File 類實(shí)例。找到下一個(gè)分隔符,繼續(xù)重復(fù)上述過程,直到分析完成。
二、使用FTP協(xié)議上傳多個(gè)文件
FTP 協(xié)議是一種用于傳輸文件的協(xié)議,它規(guī)定了相互傳輸文件的標(biāo)準(zhǔn)。這個(gè)功能在java中的實(shí)現(xiàn)是借助類來完成的。具體實(shí)現(xiàn)過程:首先與FTP服務(wù)器建立連接;初始化文件的傳輸方式,包括和兩種方式;將文件輸出到文件輸入流;讀取字節(jié)數(shù)組中的數(shù)據(jù);將數(shù)據(jù)寫入字節(jié)數(shù)組輸出流(使用方法將數(shù)據(jù)寫入網(wǎng)絡(luò)鏈接)。這樣,一個(gè)與源文件同名的文件被復(fù)制到服務(wù)器上。在這個(gè)例子中,使用了()、()、()三個(gè)方法來完成文件上傳過程。主要實(shí)現(xiàn)如下:
{ ; ; ;
void ( , 用戶, , 路徑)
{
//:FTP服務(wù)器的IP地址; user:登錄FTP服務(wù)器的用戶名
//:登錄FTP服務(wù)器的用戶名密碼; path:FTP服務(wù)器上的路徑
嘗試{ =new();
.();
.(用戶, );
.out.("!");
if (path.()!=0) .cd(path);
.(); } (ex) {.out.(ex);}
}
無效()
{嘗試{ .();
} (ex) {.out.(ex);}
}
無效()
{ =();
//從中分析出文件名,作為目標(biāo)文件名,具體方法沒有給出
試試{
os=.put();
java.io.File =new java.io.File();
is=new();
字節(jié)[] =新字節(jié)[1024];
int c;
((c=is.read())!=-1){ os.(,0,c); }
是.(); os.();
} (ex) {.out.(ex);}
}
}
() 完成與FTP服務(wù)器建立連接的功能,使用( )方法打開遠(yuǎn)程FTP服務(wù)器,然后使用(user, )方法登錄服務(wù)器。遠(yuǎn)程FTP服務(wù)器的登錄方式有兩種,一種是注冊用戶登錄,另一種是匿名登錄。前者要求用戶先注冊為服務(wù)器的客戶端,服務(wù)器會給客戶端一個(gè)登錄賬號和密碼,并根據(jù)賬號和密碼鏈接到服務(wù)器。后者要求用戶使用特殊的用戶名“”和“”,而無需注冊才能對遠(yuǎn)程主機(jī)上的公共文件進(jìn)行有限的訪問,并且許多系統(tǒng)現(xiàn)在要求用戶使用地址作為密碼。出于安全考慮php文件上傳代碼,大多數(shù)匿名 FTP 主機(jī)一般只允許遠(yuǎn)程用戶下載文件而不允許上傳文件php文件上傳代碼,這取決于 FTP 服務(wù)器的設(shè)置。用戶可以根據(jù)實(shí)際情況選擇使用兩種方式。登錄完成后使用的 () 方法將傳輸模式初始化為字節(jié)模式。 () 完成文件上傳功能。創(chuàng)建源文件的文件輸入流,將輸入流寫入字節(jié)數(shù)組,使用方法將字節(jié)數(shù)組中的數(shù)據(jù)寫入網(wǎng)絡(luò)鏈接。由于FTP服務(wù)器上的文件被打開網(wǎng)站開發(fā),數(shù)據(jù)被寫入目標(biāo)文件,從而完成文件上傳。 () 需要與服務(wù)器斷開連接。
以上只是上傳單個(gè)文件的過程。如果有多個(gè)文件,則可以多次調(diào)用此上傳過程。從以上兩種方式可以看出,使用FTP協(xié)議上傳多個(gè)文件是比較簡單易實(shí)現(xiàn)的。使用FTP協(xié)議上傳文件一般是客戶端編寫的程序,服務(wù)器端的安全設(shè)置比較復(fù)雜;而使用HTTP協(xié)議上傳文件是一個(gè)服務(wù)器端的應(yīng)用程序,安全設(shè)置比較簡單。并且通過測試發(fā)現(xiàn),F(xiàn)TP上傳方式在傳輸大文件時(shí)比HTTP上傳方式快幾十倍甚至數(shù)百倍,但在傳輸小于1M的文件時(shí)比HTTP上傳方式稍慢。因此,兩種傳輸方式各有優(yōu)勢。