Ошибка использования HttpWebRequest для загрузки файлов с PUT - PullRequest
3 голосов
/ 09 апреля 2009

У нас есть приложение .NET 2.0 WinForms, которое должно загружать файлы на сервер IIS6 через WebDav. Время от времени мы получаем жалобы от удаленного офиса, что они получают одно из следующих сообщений об ошибках

  • Базовое соединение было закрыто: при отправке произошла непредвиденная ошибка.
  • Базовое соединение было закрыто: неожиданная ошибка произошла на получить.

Это, кажется, происходит только с большими файлами (~ 20 МБ плюс). Я проверил его с помощью файла размером 40 МБ со своего домашнего компьютера и попытался поместить в спящий режим «Sleep's», чтобы симулировать медленное соединение, поэтому я подозреваю, что это связано с проблемами сети в их конце ... но

  1. ИТ в удаленном офисе не помогают
  2. Я бы хотел исключить вероятность того, что мой код ошибочен.

Итак - кто-нибудь может заметить какие-либо ошибки или предложить какие-либо обходные пути, которые могут «пуленепробиваемым» кодом против этой проблемы. Спасибо за любую помощь. Вырубленная версия кода выглядит следующим образом:

    public bool UploadFile(string localFile, string uploadUrl)
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uploadUrl);

        try
        {
            req.Method = "PUT";
            req.AllowWriteStreamBuffering = true;
            req.UseDefaultCredentials = Program.WebService.UseDefaultCredentials;
            req.Credentials = Program.WebService.Credentials;
            req.SendChunked = false;
            req.KeepAlive = true;
            Stream reqStream = req.GetRequestStream();
            FileStream rdr = new FileStream(localFile, FileMode.Open, FileAccess.Read);
            byte[] inData = new byte[4096];
            int bytesRead = rdr.Read(inData, 0, inData.Length);

            while (bytesRead > 0)
            {
                reqStream.Write(inData, 0, bytesRead);
                bytesRead = rdr.Read(inData, 0, inData.Length);
            }

            reqStream.Close();
            rdr.Close();

            System.Net.HttpWebResponse response = (HttpWebResponse)req.GetResponse();
            if (response.StatusCode != HttpStatusCode.OK && response.StatusCode!=HttpStatusCode.Created)
            {
                MessageBox.Show("Couldn't upload file");
                return false;
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
            return false;
        }
        return true;
    }

Ответы [ 6 ]

6 голосов
/ 20 мая 2009

Попробуйте установить KeepAlive в false:

req.KeepAlive = false;

Это позволит закрыть и снова открыть соединение. Это не позволит использовать постоянное соединение . Я нашел много ссылок в Интернете, которые предлагали это, чтобы решить проблему, похожую на вашу. Это релевантная ссылка .

В любом случае, не рекомендуется использовать HTTP PUT (или HTTP POST) для загрузки больших файлов. Будет лучше использовать FTP или менеджер загрузки / выгрузки. Они будут обрабатывать попытки, проблемы с подключением, тайм-ауты автоматически для вас. Загрузка также будет быстрее, и вы также можете возобновить остановленную загрузку. Если вы решили остаться с HTTP, вы должны хотя бы попытаться добавить механизм повторных попыток. Если загрузка занимает слишком много времени, высока вероятность того, что она не удастся из-за прокси-сервера, тайм-аута сервера, брандмауэра или какой-либо другой причины, по которой у вас нет кода.

5 голосов
/ 21 мая 2009

Чтобы устранить риск ошибки в вашем коде, попробуйте использовать WebClient:

using (WebClient client = new WebClient())
{
    client.UseDefaultCredentials = Program.WebService.UseDefaultCredentials;
    client.Credentials = Program.WebService.Credentials;
    client.UploadFile(uploadUrl, "PUT", localFile);
}
1 голос
/ 25 мая 2009

Проверьте, установлен ли [Включить Http Keep-Alives] в положение [включено] на вкладке [Веб-сайт] в диспетчере IIS.

1 голос
/ 20 мая 2009

Возможно, попробуйте использовать POST, но реальным виновником, вероятно, является тип контента.

Попробуйте установить

req.ContentType = "application/octet-stream";
req.ContentLength = inData.Length;

или посмотрите код в принятом ответе здесь: Загрузите файлы с HTTPWebrequest (multipart / form-data)

И мой пример, и ссылка, которую я предоставил, включают изменение ContentType - мой пример проще, но может не работать, так как большинство приложений, получающих файлы, ожидают составную

0 голосов
/ 22 мая 2009

Начните с проверки некоторых основных настроек. Значения по умолчанию любого из следующих параметров могут вызвать проблемы при загрузке файла, включая разрыв соединения. Я считаю, что IIS 6 никогда не позволит загружать файлы> 2 ГБ (даже если он может завершиться, независимо от конфигурации). Msdn хорошо описывает это .

<httpRuntime executionTimeout = "30"  maxRequestLength="200"/>

РЕДАКТИРОВАТЬ: Это, конечно, конфигурация ASP.NET, которая предполагает, что вы используете свой собственный сервер webdav или сторонний сервер в ASP.NET. Если это другой сервер webdav, вам нужно поискать эквивалент.

0 голосов
/ 09 апреля 2009

Размер загрузки может быть ограничен.

Смотрите здесь для одного обсуждения: http://www.codeproject.com/KB/aspnet/uploadlargefilesaspnet.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...