Файлы нулевого размера, загруженные с помощью FTP FileUpload - PullRequest
1 голос
/ 12 октября 2011

Недавно я читал кучу статей о загрузке по FTP в ASP.NET, и все они, кажется, имеют смысл, но каждый раз, когда я пытался их реализовать, я либо загружал пустой файл, либо его вообще не было.Вот несколько статей, которые я читал:

Онивсе замечательные статьи, но, как я уже сказал, возникают проблемы: (

Я точно знаю, в чем проблема, но не знаю, как ее исправить. Я могу передать имя файла из элемента управления FileUpload,но этот путь не существует из соображений безопасности. Однако объект StreamReader требует, чтобы был загружен полный путь к файлу, так как, черт возьми, я могу это получить? Я в своем уме!>. <</p>

Давайте используем пример Джона Петерсона, который я связал выше. Вот код:

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

Теперь моя последняя реализация выглядит следующим образом, но загруженный файл намного больше исходного.Я испорчен.Серьезно, какого чёрта я делаю не так?Вот уже два долгих дня, гррр ...

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

Большое спасибо Адаму Марасу за потрясающий ответ.Я оставлю здесь свои грубые ошибки для других, которые найдут эту ветку;)

Ответы [ 3 ]

1 голос
/ 14 октября 2011

Прежде всего, необходимо загрузить через веб-сервер, если вы собираетесь использовать ASP.NET, как это. Без установки плагина в браузере клиента или использования элемента управления ActiveX (или аналогичного) вы абсолютно не сможете загрузить напрямую с клиентского компьютера на FTP-сервер.

Я полагаю, вы загружаете двоичные файлы; в этом случае использование StreamReader s и StreamWriter s может привести к повреждению двоичного содержимого файла. Вместо этого мы можем использовать метод 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
1 голос
/ 14 октября 2011

Данные повреждены, потому что вы читаете файл, как если бы он был текстовым, но это не так.

Используйте BinaryReader вместо StreamReader, чтобы вы могли читать данные в байтах напрямую:

Dim fileContents As Byte()
Using sourceStream As New StreamReader(FileUpload1.FileContent)
  fileContents = sourceStream.ReadBytes(Int32.MaxValue)
End Using
1 голос
/ 12 октября 2011

Метод FileUpload.SaveAs() сохраняет в локальной файловой системе веб-сервера и не может выполнять запись на URI или FTP-сайт.Для этого вам нужно создать WebRequest.

См. Ссылку на MSDN для элемента управления FileUpload здесь: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload.saveas.aspx

и для использования FTP на сервереWebRequest здесь: http://msdn.microsoft.com/en-us/library/ms229715.aspx


Обратите внимание на пример, приведенный в документации FileUpload, сохраняет в c: \ temp \ uploadedfiles.Я бы посоветовал вам использовать Path.GetTempFileName() вместо этого, поскольку это гарантированно даст вам файл, который всегда можно записать независимо от того, в какой среде вы находитесь.

...