Vb.net WebDAV独立服务器(HttpListener):无法使用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说它不是有效的文件夹 我的

我目前正在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资源管理器一起工作吗? 也许我忘了一件需要的小事情,也许有人能帮我

主要代码:

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。现在一切都好了