Файлы нулевого размера, загруженные с помощью FTP FileUpload

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

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

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

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

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

Видеть? В загруженном файле нет данных :(

введите здесь описание изображения

Теперь моя последняя реализация выглядит так, но загруженный файл намного больше исходного и поврежден. Серьезно, какого черта я делаю не так? Я потратил на это два ДОЛГИХ дня, гррр...

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

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


person Chiramisu    schedule 12.10.2011    source источник
comment
@Jim: Ну, как я могу это сделать, если у сервера нет доступа к пути к файлу на стороне клиента? По крайней мере, FileUpload Control не поддерживает это.   -  person Chiramisu    schedule 12.10.2011
comment
Вы пытались сначала сохранить файл из загрузки файла, а затем отправить его на ftp-сервер?   -  person atbebtg    schedule 14.10.2011
comment
@atbebtg Нет, потому что вы должны иметь возможность отправлять его прямо на FTP. Прохождение через веб-сервер просто кажется смешным. Если это единственный способ, я понятия не имею. Я просто пытаюсь решить эту проблему по частям, но это сводит меня с ума.   -  person Chiramisu    schedule 14.10.2011


Ответы (3)


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

Я предполагаю, что вы загружаете двоичные файлы; в этом случае то, как вы используете StreamReaders и StreamWriters, может повредить двоичное содержимое файла. Вместо этого мы можем использовать метод 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
person Adam Maras    schedule 13.10.2011
comment
О БОЖЕ МОЙ!! ЭТО СРАБОТАЛО!! Мне пришлось немного изменить его, потому что вы писали в стиле C #, но с VB, лол. Серьезно, мой мозг был полностью прожарен. Я бесконечно благодарен. Большое вам спасибо!! :) - person Chiramisu; 14.10.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(), так как это гарантированно даст вам файл, который всегда можно записать, независимо от того, в какой среде вы находитесь.

person Jeremy McGee    schedule 12.10.2011
comment
Так оно и есть. Что ж, как вы можете видеть в моем коде, одна из моих попыток записывала на FTP-сервер, но на самом деле не записывала данные. Я уже просмотрел обе страницы, на которые вы ссылались ранее. Я не могу заставить код работать, используя статью WebRequest, но я посмотрю еще раз. Все равно был бы признателен за код (или отредактировал бы мой), если бы вы были так любезны. Спасибо :) - person Chiramisu; 12.10.2011
comment
Из того, что я могу сказать, ваша попытка № 3 на самом деле не записывала файл локально. Добавьте File1.SaveAs( // temp. file // ) и все будет готово. - person Jeremy McGee; 12.10.2011
comment
Я попробовал ваши предложения, но в моем загруженном файле по-прежнему нет данных :( Пожалуйста, смотрите мои обновления и скриншот в моем посте. Я очень ценю вашу помощь :) - person Chiramisu; 13.10.2011

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

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

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