Vb.net WebDAV独立服务器(HttpListener):无法使用Windows资源管理器进行映射
我目前正在VB.NET中开发一个WebDAV服务器。我试图构建的服务器应该是独立的,所以没有IIS,也没有Apache,。。。 我正在使用HttpListener类等待HTTP/WebDAV请求。 服务器将用于映射SQL server数据库中包含的文件/文件夹 我尝试将一个简单的本地文件夹映射到Windows资源管理器,作为带有IIS和Apache的网络驱动器,它是现成的。但当我试图将自己的WebDAV服务器作为网络驱动器映射到Windows资源管理器时,Windows说它不是有效的文件夹 我的服务器从Windows资源管理器接收3个请求:选项、PROPFIND和PROPFIND。 服务器向所有这些请求发送响应,如果我使用RawCap中断网络流量,我看不到XML响应中有任何错误,也看不到HTTP头中有任何错误。。。 当我尝试使用IIS或Apache时,我也嗅探到了流量,其中有一些差异,我试图加以纠正,但没有任何区别,服务器仍然不能作为Windows资源管理器中的网络驱动器工作 我还将我的代码与其他开源WebDAV服务器进行了比较,但我不明白为什么它不起作用 我还尝试将作为IIS或Apache响应发送的XML与我的服务器一起发送,但没有成功 那么,有什么具体的东西要实现,以使它与Windows资源管理器一起工作吗? 也许我忘了一件需要的小事情,也许有人能帮我 主要代码:Vb.net WebDAV独立服务器(HttpListener):无法使用Windows资源管理器进行映射,vb.net,webdav,windows-explorer,httplistener,Vb.net,Webdav,Windows Explorer,Httplistener,我目前正在VB.NET中开发一个WebDAV服务器。我试图构建的服务器应该是独立的,所以没有IIS,也没有Apache,。。。 我正在使用HttpListener类等待HTTP/WebDAV请求。 服务器将用于映射SQL server数据库中包含的文件/文件夹 我尝试将一个简单的本地文件夹映射到Windows资源管理器,作为带有IIS和Apache的网络驱动器,它是现成的。但当我试图将自己的WebDAV服务器作为网络驱动器映射到Windows资源管理器时,Windows说它不是有效的文件夹 我的
Module WebServer
#Region "Main"
Sub Main()
Dim prefixes(0) As String
prefixes(0) = "http://*:80/"
ProcessRequests(prefixes)
End Sub
#End Region
#Region "Request processing"
Private Sub HandleRequest(context As HttpListenerContext)
Dim sw = Stopwatch.StartNew()
Dim response As HttpListenerResponse = Nothing
Dim requestHandler As IMethodHandler = Nothing
Console.WriteLine(String.Format("{0:hh:mm:ss} >>> ", DateTime.Now) + context.Request.HttpMethod + " Request from : " + context.Request.UserAgent)
Console.WriteLine(" KeepAlive: {0}", context.Request.KeepAlive)
Console.WriteLine(" Local end point: {0}", context.Request.LocalEndPoint.ToString())
Console.WriteLine(" Remote end point: {0}", context.Request.RemoteEndPoint.ToString())
Console.WriteLine(" Is local? {0}", context.Request.IsLocal)
Console.WriteLine(" HTTP method: {0}", context.Request.HttpMethod)
Console.WriteLine(" Protocol version: {0}", context.Request.ProtocolVersion)
Console.WriteLine(" Is authenticated: {0}", context.Request.IsAuthenticated)
Console.WriteLine(" Is secure: {0}", context.Request.IsSecureConnection)
' Create the response
response = context.Response
response.ContentType = "text/xml"
response.ContentEncoding = System.Text.Encoding.UTF8
' User authentication
'Dim identity As HttpListenerBasicIdentity = context.User.Identity
'If Not identity.Name.Equals("test") Or Not identity.Password.Equals("test") Then
'response.StatusCode = HttpStatusCode.Unauthorized
'response.AddHeader("WWW-Authenticate", "Basic realm=""Server""")
'Else
Select Case context.Request.HttpMethod.ToUpper()
Case "OPTIONS"
requestHandler = New OPTIONS_Handler(context)
Case "GET"
requestHandler = New GET_Handler(context)
Case "HEAD"
requestHandler = New HEAD_Handler(context)
Case "PUT"
requestHandler = New PUT_Handler(context)
Case "POST"
requestHandler = New POST_Handler(context)
Case "DELETE"
requestHandler = New DELETE_Handler(context)
Case "COPY"
requestHandler = New COPY_Handler(context)
Case "MOVE"
requestHandler = New MOVE_Handler(context)
Case "MKCOL"
requestHandler = New MKCOL_Handler(context)
Case "PROPFIND"
requestHandler = New PROPFIND_Handler(context)
Case "PROPPATCH"
requestHandler = New PROPPATCH_Handler(context)
Case Else
Console.WriteLine("Unknown Command")
response.StatusCode = HttpStatusCode.NotImplemented
End Select
If Not requestHandler Is Nothing Then
requestHandler.processRequest()
End If
If response IsNot Nothing Then
response.Close()
End If
Console.WriteLine("Time : {0}", sw.Elapsed)
'End If
End Sub
Private Sub ProcessRequests(ByVal prefixes() As String)
If Not System.Net.HttpListener.IsSupported Then
Console.WriteLine( _
"Windows XP SP2, Server 2003, or higher is required to " & _
"use the HttpListener class.")
Exit Sub
End If
' URI prefixes are required
If prefixes Is Nothing OrElse prefixes.Length = 0 Then
Throw New ArgumentException("prefixes")
End If
' Create a listener and add the prefixes
Dim listener As System.Net.HttpListener = New System.Net.HttpListener()
For Each s As String In prefixes
listener.Prefixes.Add(s)
Next
Try
' Start the listener to begin listening for requests and set authentication
'listener.AuthenticationSchemes = AuthenticationSchemes.Basic
listener.Start()
Console.WriteLine("Listening...")
While True
Try
' Note: GetContext blocks while waiting for a request
Dim context As HttpListenerContext = listener.GetContext()
Dim t As New Threading.Thread(Sub() HandleRequest(context))
t.Start()
Catch ex As HttpListenerException
Console.WriteLine(ex.Message)
End Try
End While
Catch ex As HttpListenerException
Console.WriteLine(ex.Message)
Finally
' Stop listening for requests
listener.Close()
Console.WriteLine("Done Listening...")
End Try
End Sub
#End Region
End Module
选项处理程序:
Public Class OPTIONS_Handler : Implements IMethodHandler
Private context As HttpListenerContext
Private response As HttpListenerResponse
Public Sub New(ByVal ctxt As HttpListenerContext)
context = ctxt
response = context.Response
End Sub
Public Sub processRequest() Implements IMethodHandler.processRequest
response.AppendHeader("Allow", "OPTIONS, GET, HEAD, POST, PUT, DELETE, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH")
response.AppendHeader("Public", "OPTIONS, GET, HEAD, POST, PUT, DELETE, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH")
response.AppendHeader("DAV", "1, 2, ordered-collections")
response.AppendHeader("Versioning-Support", "DAV:basicversioning")
response.AppendHeader("MS-Author-Via", "DAV")
'response.AppendHeader("X_MSDAVEXT", "1")
'response.AppendHeader("Translate", "f")
response.StatusCode = HttpStatusCode.OK
End Sub
End Class
Public Class PROPFIND_Handler : Implements IMethodHandler
Private context As HttpListenerContext
Private response As HttpListenerResponse
Public Sub New(ByVal ctxt As HttpListenerContext)
context = ctxt
response = context.Response
End Sub
Public Sub processRequest() Implements IMethodHandler.processRequest
Try
context.Response.SendChunked = False
' Check if the XML request is valid and well-formed
Dim request As HttpListenerRequest = context.Request
Dim reader As XmlReader = XmlReader.Create(request.InputStream)
' See if the inputstream includes some data. If not --> Exception
Dim buffer(16 * 1024) As Byte
Dim read As Integer
Dim memstr As New MemoryStream
While (read = request.InputStream.Read(buffer, 0, buffer.Length)) > 0
memstr.Write(buffer, 0, read)
End While
If memstr.Length <> 0 Then
Dim doc As XDocument = XDocument.Load(reader)
End If
response.StatusCode = 207
Dim xmlWriter As XmlTextWriter = New XmlTextWriter("test.xml", New System.Text.UTF8Encoding(False))
'xmlWriter.Formatting = Formatting.Indented
xmlWriter.WriteStartDocument()
xmlWriter.WriteStartElement("D:multistatus")
xmlWriter.WriteAttributeString("xmlns:D", "DAV:")
xmlWriter.WriteAttributeString("xmlns:b", "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882")
' Get the requested URI
Dim requestedURI As String = context.Request.Url.LocalPath
' Get the files and folders list from the mapped folder
Dim mappedFolderInfo
If requestedURI.Equals("/") Then
mappedFolderInfo = New IO.DirectoryInfo("MappedFolder")
Else
mappedFolderInfo = New IO.DirectoryInfo("MappedFolder" + requestedURI)
End If
Dim filesList As IO.FileInfo() = mappedFolderInfo.GetFiles()
Dim foldersList As IO.DirectoryInfo() = mappedFolderInfo.GetDirectories()
' List all the files and folders and build the corresponding XML response
Dim tempFile As IO.FileInfo
Dim tempFolder As IO.DirectoryInfo
For Each tempFolder In foldersList
Dim webDavItem As New WebDAVItem()
webDavItem.CollectionYN = True
webDavItem.ContentLength = 0
webDavItem.CreationDate = tempFolder.CreationTime
webDavItem.LastModifDate = tempFolder.LastWriteTime
webDavItem.Name = tempFolder.Name + "/"
webDavItem.Path = requestedURI
webDavItem.BuildXmlResponse(xmlWriter)
Next
For Each tempFile In filesList
Dim webDavItem As New WebDAVItem()
webDavItem.CollectionYN = False
webDavItem.ContentLength = tempFile.Length
webDavItem.CreationDate = tempFile.CreationTime
webDavItem.LastModifDate = tempFile.LastWriteTime
webDavItem.Name = tempFile.Name
webDavItem.Path = requestedURI
webDavItem.BuildXmlResponse(xmlWriter)
Next
xmlWriter.Close()
Dim f As FileStream = File.OpenRead("test.xml")
Dim fileData(f.Length) As Byte
response.ContentLength64 = f.Length
f.Read(fileData, 0, f.Length)
f.Close()
response.OutputStream.Write(fileData, 0, response.ContentLength64)
Catch ex As Exception
Console.WriteLine("Exception while handling PROPFIND : " + ex.Message)
response.StatusCode = HttpStatusCode.BadRequest
End Try
End Sub
End Class
以及PROPFIND处理程序:
Public Class OPTIONS_Handler : Implements IMethodHandler
Private context As HttpListenerContext
Private response As HttpListenerResponse
Public Sub New(ByVal ctxt As HttpListenerContext)
context = ctxt
response = context.Response
End Sub
Public Sub processRequest() Implements IMethodHandler.processRequest
response.AppendHeader("Allow", "OPTIONS, GET, HEAD, POST, PUT, DELETE, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH")
response.AppendHeader("Public", "OPTIONS, GET, HEAD, POST, PUT, DELETE, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH")
response.AppendHeader("DAV", "1, 2, ordered-collections")
response.AppendHeader("Versioning-Support", "DAV:basicversioning")
response.AppendHeader("MS-Author-Via", "DAV")
'response.AppendHeader("X_MSDAVEXT", "1")
'response.AppendHeader("Translate", "f")
response.StatusCode = HttpStatusCode.OK
End Sub
End Class
Public Class PROPFIND_Handler : Implements IMethodHandler
Private context As HttpListenerContext
Private response As HttpListenerResponse
Public Sub New(ByVal ctxt As HttpListenerContext)
context = ctxt
response = context.Response
End Sub
Public Sub processRequest() Implements IMethodHandler.processRequest
Try
context.Response.SendChunked = False
' Check if the XML request is valid and well-formed
Dim request As HttpListenerRequest = context.Request
Dim reader As XmlReader = XmlReader.Create(request.InputStream)
' See if the inputstream includes some data. If not --> Exception
Dim buffer(16 * 1024) As Byte
Dim read As Integer
Dim memstr As New MemoryStream
While (read = request.InputStream.Read(buffer, 0, buffer.Length)) > 0
memstr.Write(buffer, 0, read)
End While
If memstr.Length <> 0 Then
Dim doc As XDocument = XDocument.Load(reader)
End If
response.StatusCode = 207
Dim xmlWriter As XmlTextWriter = New XmlTextWriter("test.xml", New System.Text.UTF8Encoding(False))
'xmlWriter.Formatting = Formatting.Indented
xmlWriter.WriteStartDocument()
xmlWriter.WriteStartElement("D:multistatus")
xmlWriter.WriteAttributeString("xmlns:D", "DAV:")
xmlWriter.WriteAttributeString("xmlns:b", "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882")
' Get the requested URI
Dim requestedURI As String = context.Request.Url.LocalPath
' Get the files and folders list from the mapped folder
Dim mappedFolderInfo
If requestedURI.Equals("/") Then
mappedFolderInfo = New IO.DirectoryInfo("MappedFolder")
Else
mappedFolderInfo = New IO.DirectoryInfo("MappedFolder" + requestedURI)
End If
Dim filesList As IO.FileInfo() = mappedFolderInfo.GetFiles()
Dim foldersList As IO.DirectoryInfo() = mappedFolderInfo.GetDirectories()
' List all the files and folders and build the corresponding XML response
Dim tempFile As IO.FileInfo
Dim tempFolder As IO.DirectoryInfo
For Each tempFolder In foldersList
Dim webDavItem As New WebDAVItem()
webDavItem.CollectionYN = True
webDavItem.ContentLength = 0
webDavItem.CreationDate = tempFolder.CreationTime
webDavItem.LastModifDate = tempFolder.LastWriteTime
webDavItem.Name = tempFolder.Name + "/"
webDavItem.Path = requestedURI
webDavItem.BuildXmlResponse(xmlWriter)
Next
For Each tempFile In filesList
Dim webDavItem As New WebDAVItem()
webDavItem.CollectionYN = False
webDavItem.ContentLength = tempFile.Length
webDavItem.CreationDate = tempFile.CreationTime
webDavItem.LastModifDate = tempFile.LastWriteTime
webDavItem.Name = tempFile.Name
webDavItem.Path = requestedURI
webDavItem.BuildXmlResponse(xmlWriter)
Next
xmlWriter.Close()
Dim f As FileStream = File.OpenRead("test.xml")
Dim fileData(f.Length) As Byte
response.ContentLength64 = f.Length
f.Read(fileData, 0, f.Length)
f.Close()
response.OutputStream.Write(fileData, 0, response.ContentLength64)
Catch ex As Exception
Console.WriteLine("Exception while handling PROPFIND : " + ex.Message)
response.StatusCode = HttpStatusCode.BadRequest
End Try
End Sub
End Class
多谢各位 问题已部分解决 在响应XML中,似乎是creationdate的格式不正确。格式正确,但日期字符串末尾缺少一个“Z”字母。。。别问为什么,我不知道: 我硬编码了这封信,Windows资源管理器接受将服务器映射为网络驱动器。 当资源管理器尝试检索映射文件夹的内容时,仍然会出现一些错误,但要纠正这些错误应该不会太困难 编辑:问题现在完全解决了。这只是PROPFIND期间发生的NullRefException。现在一切都好了