科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件ASP.NET实现FTP文件上载类

ASP.NET实现FTP文件上载类

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

我偶然发现在Microsoft的MSDN中已经发表过处理FTP的一个完整的类

作者:子夜编译 来源:天极网 2007年11月7日

关键字: ASP.NET ftp 上载类 Windows

  • 评论
  • 分享微博
  • 分享邮件
最近,分配给我一个项目,这个项目已成功运转,在这个项目中我需要允许我们的用户经由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

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章