top
Loading...
ASP.NET實現FTP文件上載類
最近,分配給我一個項目,這個項目已成功運轉,在這個項目中我需要允許我們的用戶經由XML和FTP向另一個公司輸出它們的數據。在研究了所有的ASP.NET書籍以后,我們發現任何地方都沒有FTP方法,并且花費了一些時間在因特網上搜索相關的例子。我弄清楚了那一點。網絡沒有自產的FTP支持。我開始去信心并且以A.被迫使用一些舊的ASP代碼和Com或者B.停止下來并且購買某些部件。

不過,我最終偶然發現在Microsoft的MSDN中已經發表過處理FTP的一個完整的類。在這個類中的代碼有一點冗長,所以對Microsoft的聲譽有影響,雇員必須停下來并且將它們砍去。

‘在Visual Basic.NET 2002中進行調用。你會
‘將數據移動8位。在Visual Basic .NET 2002中,你必須
‘這個數乘以2的8次方
‘端口=parts(4)*(2^8)

‘進行調用,并且接著以Visual Basic .NET 2003進行注釋當前行。
port = parts(4) << 8

我們還使用Visual Studio 2002,所以得到這個注釋是一件好事。

為了測試這個類,我建立了默認的FTP網頁,以允許匿名用戶進行存取。


圖1

圖2


之后,通過代碼調用是件輕而易舉的事。

Dim ftpClient As New clsFTP("localhost", "", "anonymous", "", 80)
If (ftpClient.Login() = True) Then
‘創建一個新文件夾
ftpClient.CreateDirectory("FTPFOLDERNEW")

‘將新的文件夾設置為活動文件夾。
ftpClient.ChangeDirectory("FTPFOLDERNEW")

‘設置FTP模式

ftpClient.SetBinaryMode(True)

‘從你的硬盤上上載一個文件到FTP網頁
ftpClient.UploadFile(Server.MapPath("SampleFile.xml"))

‘對上載文件重命名
ftpClient.RenameFile("SampleFile.xml", "SampleFile_new.xml")

‘刪除一個文件
ftpClient.DeleteFile("SampleFile_new.xml")

‘總是關閉鏈接,確保沒有任何不在使用中的FTP鏈接
‘檢查你是否登錄到FTP服務器,并且接著關閉鏈接
ftpClient.CloseConnection()
End If

瀏覽ASP.NET論壇,我發現對ASP.NET特征的一個論壇,在那里一個用戶注釋到擁有一個自己的FTP庫該是多么地不錯呀。保羅.威爾遜,一個ASP的內行,答復到它已開始2.0了。非常明確它是受歡迎的。

以下是在MSDN文章中找到的對FTP客戶端類的完整代碼。怎么使用Visual Basic .NET來存取一個文件傳輸協議網頁呢?

‘這個類允許你使用Visual Basic.NET對FTP網頁執行直接鏈接。
‘這個類支持以下FTP命令:
‘-Upload 一個文件
‘-Download一個文件
‘-Create 一個目錄
‘-Remove 一個目錄
‘-改變目錄
‘-Remove 一個文件
‘-Rename 一個文件
‘-Set 遠程用戶的用戶名
‘-Set 遠程用戶的密碼

Imports System
Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Net.Sockets

‘FTP 類

Public Class clsFTP
#Region "Class Variable Declarations"
Private m_sRemoteHost, m_sRemotePath, m_sRemoteUser As String
Private m_sRemotePassword, m_sMess As String
Private m_iRemotePort, m_iBytes As Int32
Private m_objClientSocket As Socket
Private m_iRetValue As Int32
Private m_bLoggedIn As Boolean
Private m_sMes, m_sReply As String

‘設置用戶來對FTP服務器讀取和寫入數據的數據包的大小
‘對下列具體大小

Public Const BLOCK_SIZE = 512
Private m_aBuffer(BLOCK_SIZE) As Byte
Private ASCII As Encoding = Encoding.ASCII
Public flag_bool As Boolean
‘普通變量定義
Private m_sMessageString As String
#End Region

#Region "Class Constructors"

‘Main類的構造器
Public Sub New()
m_sRemoteHost = "microsoft"
m_sRemotePath = "."
m_sRemoteUser = "anonymous"
m_sRemotePassword = ""
m_sMessageString = ""
m_iRemotePort = 21
m_bLoggedIn = False
End Sub

‘參數化的構造器

Public Sub New(ByVal sRemoteHost As String, _
ByVal sRemotePath As String, _
ByVal sRemoteUser As String, _
ByVal sRemotePassword As String, _
ByVal iRemotePort As Int32)

m_sRemoteHost = sRemoteHost
m_sRemotePath = sRemotePath
m_sRemoteUser = sRemoteUser
m_sRemotePassword = sRemotePassword
m_sMessageString = ""
m_iRemotePort = 21
m_bLoggedIn = False

End Sub

#End Region

#Region "Public Properties"

‘設置或得到你想鏈接的FTP服務器的名稱

Public Property RemoteHostFTPServer() As String
‘得到FTP服務器的名稱
Get
Return m_sRemoteHost
End Get

‘設置FTP服務器的名稱

Set(ByVal Value As String)
m_sRemoteHost = Value
End Set
End Property



‘設置或得到你想鏈接的FTP服務器的FTP端口

Public Property RemotePort() As Int32

‘得到FTP端口號

Get
Return m_iRemotePort
End Get

‘設置FTP端口數號

Set(ByVal Value As Int32)
m_iRemotePort = Value
End Set
End Property

‘設置或得到你想鏈接的FTP服務器的遠程路徑

Public Property RemotePath() As String

‘得到遠程路徑
Get
Return m_sRemotePath
End Get
‘設置遠程路徑
Set(ByVal Value As String)
m_sRemotePath = Value
End Set
End Property

‘設置你想鏈接的遠程FTP服務器的密碼

Public Property RemotePassword() As String
Get
Return m_sRemotePassword
End Get
Set(ByVal Value As String)
m_sRemotePassword = Value
End Set
End Property

‘設置或得到你想鏈接遠程的FTP服務器的用戶

Public Property RemoteUser() As String
Get
Return m_sRemoteUser
End Get

Set(ByVal Value As String)
m_sRemoteUser = Value
End Set
End Property

‘設置messagestring類

Public Property MessageString() As String
Get
Return m_sMessageString
End Get

Set(ByVal Value As String)
m_sMessageString = Value
End Set
End Property

#End Region
#Region "Public Subs and Functions"

‘從文件系統中返回一個文件列表。在string()函數中返回文件。

Public Function GetFileList(ByVal sMask As String) As String()
Dim cSocket As Socket
Dim bytes As Int32
Dim seperator As Char = ControlChars.Lf
Dim mess() As String

m_sMes = ""
‘檢查你是否登錄到FTP服務器上
If (Not (m_bLoggedIn)) Then
Login()
End If

cSocket = CreateDataSocket()
‘發送FTP命令

SendCommand("NLST " & sMask)
If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If
m_sMes = ""
Do While (True)
m_aBuffer.Clear(m_aBuffer, 0, m_aBuffer.Length)
bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
m_sMes += ASCII.GetString(m_aBuffer, 0, bytes)

If (bytes < m_aBuffer.Length) Then
Exit Do
End If
Loop

mess = m_sMes.Split(seperator)
cSocket.Close()
ReadReply()

If (m_iRetValue <> 226) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

Return mess
End Function

‘得到FTP服務器上的文件大小
Public Function GetFileSize(ByVal sFileName As String) As Long
Dim size As Long

If (Not (m_bLoggedIn)) Then
Login()
End If

‘發送一個FTP命令
SendCommand("SIZE " & sFileName)
size = 0

If (m_iRetValue = 213) Then
size = Int64.Parse(m_sReply.Substring(4))
Else
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

Return size
End Function

‘登錄FTP服務器

Public Function Login() As Boolean
m_objClientSocket = _
New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim ep As New IPEndPoint(Dns.Resolve(m_sRemoteHost).AddressList(0), m_iRemotePort)

Try
m_objClientSocket.Connect(ep)
Catch ex As Exception
MessageString = m_sReply
Throw New IOException("Cannot connect to the remote server")
End Try

ReadReply()
If (m_iRetValue <> 220) Then
CloseConnection()
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

‘為了發送一個對服務器的用戶登錄ID,發送一個FTP命令

SendCommand("USER " & m_sRemoteUser)

If (Not (m_iRetValue = 331 Or m_iRetValue = 230)) Then
Cleanup()
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

If (m_iRetValue <> 230) Then
‘為了發送一個對服務器的用戶密碼,發送一個FTP命令
SendCommand("PASS " & m_sRemotePassword)
If (Not (m_iRetValue = 230 Or m_iRetValue = 202)) Then
Cleanup()
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If
End If

m_bLoggedIn = True
‘為了改變映射的遠程服務器的文件夾的目錄,調用用戶定義的ChangeDirectory函數
ChangeDirectory(m_sRemotePath)

‘返回最終結果
Return m_bLoggedIn
End Function

‘如果模式值為真,對下載設置為二進制模式。否則,設置為ASCII模式

Public Sub SetBinaryMode(ByVal bMode As Boolean)
If (bMode) Then
‘發送FTP命令,設置為二進制模式
‘(TYPE是一種用作說明請求類型的FTP命令.)
SendCommand("TYPE I")
Else
‘發送FTP命令,設置ASCII模式。
‘(TYPE是一種用作說明請求類型的FTP命令。)
SendCommand("TYPE A")
End If
If (m_iRetValue <> 200) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If
End Sub

‘向配置好的本地目錄下載一個文件。保持文件名一樣。

Public Sub DownloadFile(ByVal sFileName As String)
DownloadFile(sFileName, "", False)
End Sub

‘向一個配置好的本地文件夾下載一個遠程文件。保持文件名一樣。 Public Sub DownloadFile(ByVal sFileName As String, _

ByVal bResume As Boolean)

DownloadFile(sFileName, "", bResume)

End Sub

‘對本地文件名下載一個遠程文件。你必須包含一個路徑。

‘本地文件名將會創建或者將會被重寫,但是路徑必須存在。

Public Sub DownloadFile(ByVal sFileName As String, _
ByVal sLocalFileName As String)
DownloadFile(sFileName, sLocalFileName, False)
End Sub

‘對一個本地文件名下載一個遠程文件。你必須包含一個路徑。設置恢復標志。本地文件名將會被創建或被重寫,但是本地路徑必須存在。

Public Sub DownloadFile(ByVal sFileName As String, _
ByVal sLocalFileName As String, _
ByVal bResume As Boolean)

Dim st As Stream
Dim output As FileStream
Dim cSocket As Socket
Dim offset, npos As Long

If (Not (m_bLoggedIn)) Then
Login()
End If

SetBinaryMode(True)
If (sLocalFileName.Equals("")) Then
sLocalFileName = sFileName
End If
If (Not (File.Exists(sLocalFileName))) Then
st = File.Create(sLocalFileName)
st.Close()
End If

output = New FileStream(sLocalFileName, FileMode.Open)
cSocket = CreateDataSocket()
offset = 0

If (bResume) Then
offset = output.Length

If (offset > 0) Then
‘發送一個FTP命令重新啟動
SendCommand("REST " & offset)
If (m_iRetValue <> 350) Then
offset = 0
End If
End If

If (offset > 0) Then
npos = output.Seek(offset, SeekOrigin.Begin)
End If
End If

‘發送一個FTP命令重新找到一個文件。
SendCommand("RETR " & sFileName)

If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

Do While (True)
m_aBuffer.Clear(m_aBuffer, 0, m_aBuffer.Length)
m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
output.Write(m_aBuffer, 0, m_iBytes)

If (m_iBytes <= 0) Then
Exit Do
End If
Loop

output.Close()
If (cSocket.Connected) Then
cSocket.Close()
End If

ReadReply()
If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

End Sub

‘這是一個從你的本地硬盤上向你的FTP文件夾中上載文件的函數

Public Sub UploadFile(ByVal sFileName As String)
UploadFile(sFileName, False)
End Sub

‘這是一個從你的本地硬盤上向你的FTP網頁上上載的函數和設置恢復標志

Public Sub UploadFile(ByVal sFileName As String, _
ByVal bResume As Boolean)

Dim cSocket As Socket
Dim offset As Long
Dim input As FileStream
Dim bFileNotFound As Boolean

If (Not (m_bLoggedIn)) Then
Login()
End If

cSocket = CreateDataSocket()
offset = 0

If (bResume) Then
Try
SetBinaryMode(True)
offset = GetFileSize(sFileName)
Catch ex As Exception
offset = 0
End Try
End If

If (offset > 0) Then
SendCommand("REST " & offset)
If (m_iRetValue <> 350) Then
‘遠程服務器可能不支持恢復。
offset = 0
End If
End If

‘發送一個FTP命令,存儲一個文件。 SendCommand("STOR " & Path.GetFileName(sFileName))

If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

‘在上載之前,檢查文件是否存在。
bFileNotFound = False
If (File.Exists(sFileName)) Then
‘打開輸入流讀取源文件
input = New FileStream(sFileName, FileMode.Open)
If (offset <> 0) Then
input.Seek(offset, SeekOrigin.Begin)
End If

‘上載這個文件

m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
Do While (m_iBytes > 0)
cSocket.Send(m_aBuffer, m_iBytes, 0)
m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
Loop
input.Close()
Else
bFileNotFound = True
End If

If (cSocket.Connected) Then
cSocket.Close()
End If

‘如果找不到文件,檢查返回值

If (bFileNotFound) Then
MessageString = m_sReply
Throw New IOException("The file: “& sFileName & " was not found. " & _
"Cannot upload the file to the FTP site")
End If

ReadReply()

If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If
End Sub

‘從遠程FTP服務器上刪除一個文件。

Public Function DeleteFile(ByVal sFileName As String) As Boolean
Dim bResult As Boolean

bResult = True
If (Not (m_bLoggedIn)) Then
Login()
End If
‘發送一個FTP命令,刪除一個文件。
SendCommand("DELE " & sFileName)
If (m_iRetValue <> 250) Then
bResult = False
MessageString = m_sReply
End If

‘返回最終結果

Return bResult
End Function

‘在遠程FTP服務器上重命名一個文件

Public Function RenameFile(ByVal sOldFileName As String, _
ByVal sNewFileName As String) As Boolean

Dim bResult As Boolean
bResult = True
If (Not (m_bLoggedIn)) Then
Login()
End If
‘發送一個FTP命令,對一個文件重命名
SendCommand("RNFR " & sOldFileName)
If (m_iRetValue <> 350) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

‘發送一個FTP命令,對一個文件更改為新名稱
‘如果新的文件名存在,會被覆蓋。
SendCommand("RNTO " & sNewFileName)
If (m_iRetValue <> 250) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If
‘返回最終結果
Return bResult
End Function

‘這是一個在遠程服務器上創建目錄的函數
Public Function CreateDirectory(ByVal sDirName As String) As Boolean
Dim bResult As Boolean

bResult = True
If (Not (m_bLoggedIn)) Then
Login()
End If
‘發送一個FTP命令,在FTP服務器上制作一個目錄
SendCommand("MKD " & sDirName)
If (m_iRetValue <> 257) Then
bResult = False
MessageString = m_sReply
End If

‘返回最終結果
Return bResult
End Function

‘這是一個在遠程FTP服務器上刪除目錄的函數

Public Function RemoveDirectory(ByVal sDirName As String) As Boolean

Dim bResult As Boolean
bResult = True
‘檢查是否已登錄FTP服務器
If (Not (m_bLoggedIn)) Then
Login()
End If
‘發送一個FTP命令,刪除在FTP服務器上的目錄
SendCommand("RMD " & sDirName)
If (m_iRetValue <> 250) Then
bResult = False
MessageString = m_sReply
End If

‘返回最終結果
Return bResult
End Function

‘這是一個用來在遠程FTP服務器上改變當前工作目錄的函數。

Public Function ChangeDirectory(ByVal sDirName As String) As Boolean
Dim bResult As Boolean

bResult = True
‘檢查你是否在根目錄
If (sDirName.Equals(".")) Then
Exit Function
End If
‘檢查是否已登錄FTP服務器
If (Not (m_bLoggedIn)) Then
Login()
End If
‘發送FTP命令,改變在FTP服務器上的目錄。
SendCommand("CWD " & sDirName)
If (m_iRetValue <> 250) Then
bResult = False
MessageString = m_sReply
End If

Me.m_sRemotePath = sDirName

‘返回最終結果
Return bResult
End Function

‘關閉遠程服務器的FTP鏈接

Public Sub CloseConnection()
If (Not (m_objClientSocket Is Nothing)) Then
‘發送一個FTP命令,結束FTP服務系統。
SendCommand("QUIT")
End If

Cleanup()
End Sub

#End Region

#Region "Private Subs and Functions"

‘從FTP服務器得到回應。

Private Sub ReadReply()
m_sMes = ""
m_sReply = ReadLine()
m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3))
End Sub

‘清除一些變量

Private Sub Cleanup()
If Not (m_objClientSocket Is Nothing) Then
m_objClientSocket.Close()
m_objClientSocket = Nothing
End If

m_bLoggedIn = False
End Sub

‘從FTP服務器讀取一行。

Private Function ReadLine(Optional ByVal bClearMes As Boolean = False) As String
Dim seperator As Char = ControlChars.Lf
Dim mess() As String

If (bClearMes) Then
m_sMes = ""
End If
Do While (True)
m_aBuffer.Clear(m_aBuffer, 0, BLOCK_SIZE)
m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes)
If (m_iBytes < m_aBuffer.Length) Then
Exit Do
End If
Loop

mess = m_sMes.Split(seperator)
If (m_sMes.Length > 2) Then
m_sMes = mess(mess.Length - 2)
Else
m_sMes = mess(0)
End If

If (Not (m_sMes.Substring(3, 1).Equals(" "))) Then
Return ReadLine(True)
End If

Return m_sMes
End Function

‘這是一個你想鏈接的FTP服務器用于發送命令的函數。

Private Sub SendCommand(ByVal sCommand As String)
sCommand = sCommand & ControlChars.CrLf
Dim cmdbytes As Byte() = ASCII.GetBytes(sCommand)
m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0)
ReadReply()
End Sub

‘創建一個數據包 Private Function CreateDataSocket() As Socket

Dim index1, index2, len As Int32
Dim partCount, i, port As Int32
Dim ipData, buf, ipAddress As String
Dim parts(6) As Int32
Dim ch As Char
Dim s As Socket
Dim ep As IPEndPoint
‘發送一個FTP命令,用于被動數據鏈接

SendCommand("PASV")
If (m_iRetValue <> 227) Then
MessageString = m_sReply
Throw New IOException(m_sReply.Substring(4))
End If

index1 = m_sReply.IndexOf("(")
index2 = m_sReply.IndexOf(")")
ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1)

len = ipData.Length
partCount = 0
buf = ""

For i = 0 To ((len - 1) And partCount <= 6)
ch = Char.Parse(ipData.Substring(i, 1))
If (Char.IsDigit(ch)) Then
buf += ch
ElseIf (ch <> ",") Then
MessageString = m_sReply
Throw New IOException("Malformed PASV reply: " & m_sReply)
End If

If ((ch = ",") Or (i + 1 = len)) Then
Try
parts(partCount) = Int32.Parse(buf)
partCount += 1
buf = ""
Catch ex As Exception
MessageString = m_sReply
Throw New IOException("Malformed PASV reply: " & m_sReply)
End Try

End If

Next

ipAddress = parts(0) & "." & parts(1) & "." & parts(2) & "." & parts(3)

‘在Visual Basic .Net 2002中進行調用。你想移動8位。在Visual Basic .NET 2002中,你必須將此數乘2的8次方。
‘端口=parts(4)*(2^8)
‘進行這個調用,并且用Visual Basic .NET 2003解釋當前行。

port = parts(4) << 8
‘確定數據端口數
port = port + parts(5)
s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
ep = New IPEndPoint(Dns.Resolve(ipAddress).AddressList(0), port)
Try
s.Connect(ep)
Catch ex As Exception
MessageString = m_sReply
Throw New IOException("Cannot connect to remote server.")
‘如果你不能鏈接到特定的FTP服務器,也就是說,將其布爾值設置為false。
flag_bool = False
End Try

‘如果你能夠鏈接到特定的FTP服務器,將布爾值設置為true。

flag_bool = True
Return s
End Function

#End Region
End Class

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗