ドキュメントを Html Agility パックで保存した後、(FtpWebRequest を介して) ドキュメントをアップロードする際に問題が発生しました。HTML ファイルを編集して stringWriter に保存し、サーバーにアップロードしようとしています。こんな風に書類を保存しているのですが……
doc.OptionAutoCloseOnEnd = True
doc.OptionWriteEmptyNodes = True
Dim sr As New StringWriter
doc.Save(sr)
そして、msdn のものと同様に asyncFtpUpload サブを使用してアップロードしますが、いくつかの変更のみを行います (ファイル名の代わりに文字列を使用します)。
http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx#Y3024
この結果、アップロードされたファイルの最後のバイトが切り取られます。サーバー上でそのファイルのソース コードを見ると、<\html> タグがありません。私はコードをデバッグし、doc.save() で作成された文字列は正しく、アップロード ルーチンで getBytes() を使用しても正しく、requestStream 書き込みメソッドはストリームの正しい長さを書き込みます。このコードで何が起こっているのかわかりません。
誰でもこれを理解するのを手伝ってもらえますか?
コードは次のとおりです。
Dim outStream As MemoryStream = New MemoryStream(ASCIIEncoding.Default.GetBytes(str))
Dim uploader As AsynchronousFtpUpLoader = New AsynchronousFtpUpLoader
uploader.startUpload(pag, outStream)
そしてクラス:
パブリック クラス AsynchronousFtpUpLoader
Public Sub startUpload(ByVal pag As FtpPage, ByVal stream As Stream)
Try
Dim waitObject As ManualResetEvent
Dim target As New Uri(pag.currentUrl)
Dim state As New FtpState()
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(target), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.UploadFile
request.UseBinary = False
request.Credentials = New NetworkCredential(pag.login, pag.password)
state.Request = request
state.stream = stream
' Get the event to wait on.
waitObject = state.OperationComplete
' Asynchronously get the stream for the file contents.
request.BeginGetRequestStream(New AsyncCallback(AddressOf EndGetStreamCallback), state)
' Block the current thread until all operations are complete.
waitObject.WaitOne()
' The operations either completed or threw an exception.
If state.OperationException IsNot Nothing Then
Throw state.OperationException
Else
End If
Catch ex As Exception
End Try
End Sub
Private Shared Sub EndGetStreamCallback(ByVal ar As IAsyncResult)
Dim state As FtpState = DirectCast(ar.AsyncState, FtpState)
Dim requestStream As Stream = Nothing
Try
requestStream = state.Request.EndGetRequestStream(ar)
Const bufferLength As Integer = 2048
Dim buffer As Byte() = New Byte(bufferLength) {}
Dim readBytes As Integer = 0
Dim stream As MemoryStream = state.stream
Do
readBytes = stream.Read(buffer, 0, bufferLength)
If readBytes <> 0 Then
requestStream.Write(buffer, 0, readBytes)
End If
Loop While readBytes <> 0
requestStream.Flush()
state.stream.Close()
requestStream.Close()
state.Request.BeginGetResponse(New AsyncCallback(AddressOf EndGetResponseCallback), state)
Catch e As Exception
state.OperationException = e
state.OperationComplete.[Set]()
Return
End Try
End Sub
Private Shared Sub EndGetResponseCallback(ByVal ar As IAsyncResult)
Dim state As FtpState = DirectCast(ar.AsyncState, FtpState)
Dim response As FtpWebResponse = Nothing
Try
response = DirectCast(state.Request.EndGetResponse(ar), FtpWebResponse)
response.Close()
state.StatusDescription = response.StatusDescription
state.OperationComplete.[Set]()
Catch e As Exception
state.OperationException = e
state.OperationComplete.[Set]()
End Try
End Sub