使用FTP FileUpload上传的零大小文件

时间:2011-10-12 18:04:07

标签: asp.net vb.net ftp client ftp-server

我最近在ASP.NET上阅读了大量关于FTP上传的文章,它们似乎都有意义,但每次我尝试实现它们时,我都会上传一个空文件,或者根本没有文件。以下是我一直在阅读的一些文章:

他们都是伟大的文章,但就像我说的那样,有问题:(

我确切地知道问题是什么,但我不知道如何解决它。我可以从FileUpload控件传递文件名,但出于安全考虑,该路径不存在。但是,StreamReader对象需要上传文件的完全限定路径,那么我该怎么做呢?我的智慧结束了! >。<

让我们使用上面链接的John Peterson的例子。这是代码:

Protected Sub btnUploadFile_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim myFtpWebRequest As FtpWebRequest
    Dim myFtpWebResponse As FtpWebResponse
    Dim myStreamWriter As StreamWriter

    myFtpWebRequest = WebRequest.Create("ftp://ftp_server_name/filename.ext")
    myFtpWebRequest.Method = WebRequestMethods.Ftp.UploadFile
    myFtpWebRequest.UseBinary = True

    myStreamWriter = New StreamWriter(myFtpWebRequest.GetRequestStream())

    'IT BREAKS HERE BECAUSE THE CLIENT PATH IS WRONG!!
    myStreamWriter.Write(New StreamReader(Server.MapPath("filename.ext")).ReadToEnd)
    myStreamWriter.Close()

    myFtpWebResponse = myFtpWebRequest.GetResponse()
    myFtpWebResponse.Close()
End Sub

请参阅?上传文件中没有数据:(

enter image description here

现在我的最新实现看起来像这样,但上传的文件比源文件大得多,而且已损坏。说真的,我做错了什么?我已经在这两天了,grrr ......

Protected Sub btnUploadFile2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim myFtpWebRequest As FtpWebRequest
    Dim myFtpWebResponse As FtpWebResponse

    filename = Path.GetFileName(FileUpload1.FileName)

    myFtpWebRequest = CType(WebRequest.Create(ftpServer + ftpPath + filename), FtpWebRequest)
    myFtpWebRequest.Method = WebRequestMethods.Ftp.UploadFile
    myFtpWebRequest.UseBinary = True

    'NEW APPROACH USING THE STREAM OF THE FILE FROM THE FileUpload Control
    'CORRECT BYTE LENGTH - in sourceStream.BaseStream
    Dim sourceStream As New StreamReader(FileUpload1.FileContent)
    'WRONG BYTE LENGTH - in sourceStream.ReadToEnd()
    Dim fileContents As Byte() = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd())
    sourceStream.Close()
    myFtpWebRequest.ContentLength = fileContents.Length

    Dim requestStream As Stream = myFtpWebRequest.GetRequestStream()
    requestStream.Write(fileContents, 0, fileContents.Length)
    requestStream.Close()

    myFtpWebResponse = CType(myFtpWebRequest.GetResponse(), FtpWebResponse)
    myFtpWebResponse.Close()
End Sub

非常感谢Adam Maras给出的惊人答案。我会把我的错误留给别人,让其他人从中受益,找到这个帖子;)

3 个答案:

答案 0 :(得分:1)

FileUpload.SaveAs()方法保存到 Web服务器的本地文件系统,无法写入URI或FTP站点。为此,您需要创建WebRequest

请在此处查看FileUpload控件的MSDN参考:http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload.saveas.aspx

以及在此使用WebRequest的FTP:http://msdn.microsoft.com/en-us/library/ms229715.aspx


请注意,FileUpload文档中给出的示例保存到c:\ temp \ uploadedfiles。我建议您使用Path.GetTempFileName(),因为这可以保证为您提供一个无论您在何种环境下都可以随时写入的文件。

答案 1 :(得分:1)

首先,如果您打算像这样使用ASP.NET,那么必须通过Web服务器上传。如果没有在客户端的浏览器上安装插件或使用ActiveX控件(或类似的),您绝对无法直接从客户端计算机上传到FTP服务器。

我假设您正在上传二进制文件;如果是这种情况,您使用StreamReaderStreamWriter的方式可能会破坏文件的二进制内容。相反,我们可以使用Stream.CopyTo方法将数据逐字地从一个流移动到另一个流。

我已修改您的方法以改为使用此模式:

Protected Sub btnUploadFile2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim myFtpWebRequest As FtpWebRequest
    Dim myFtpWebResponse As FtpWebResponse

    filename = Path.GetFileName(FileUpload1.FileName)

    myFtpWebRequest = CType(WebRequest.Create(ftpServer + ftpPath + filename), FtpWebRequest)
    myFtpWebRequest.Method = WebRequestMethods.Ftp.UploadFile
    myFtpWebRequest.UseBinary = True

    Dim myFileStream As Stream = FileUpload1.FileContent
    myFtpWebRequest.ContentLength = myFileStream.Length

    Dim requestStream As Stream = myFtpWebRequest.GetRequestStream()
    myFileStream.CopyTo(requestStream)
    requestStream.Close()

    myFtpWebResponse = CType(myFtpWebRequest.GetResponse(), FtpWebResponse)
    myFtpWebResponse.Close()
End Sub

答案 2 :(得分:1)

数据被破坏是因为您正在读取文件,就好像它是文本一样,但事实并非如此。

使用BinaryReader代替StreamReader,以便您可以直接将数据读取为字节:

Dim fileContents As Byte()
Using sourceStream As New StreamReader(FileUpload1.FileContent)
  fileContents = sourceStream.ReadBytes(Int32.MaxValue)
End Using