none
HttpRequest 2 RRS feed

  • Вопрос

  •  Пожалуйста, проверьте все ли правильно сделано в UploadFilesToRemoteUrl.


                                                                                                                                                    public static void UploadFilesToRemoteUrl(string url, string[] files, string
    logpath, NameValueCollection nvc)
            {
                url = "http://" + url + "/";
                //Тело запроса -
                HttpWebRequest ReqLoad = (HttpWebRequest)WebRequest.Create(url);
                #region Параметры (отправщика) посылки
                long length = 0;
                string boundary = "----------------------------" +
                DateTime.Now.Ticks.ToString("x");
                ReqLoad.ContentType = "multipart/form-data; boundary=" +
                boundary;
                ReqLoad.Method = "POST";
                ReqLoad.KeepAlive = true;
                ReqLoad.Credentials =
                System.Net.CredentialCache.DefaultCredentials;
                #endregion
                //Создаём поток памяти - резервное хранилище которого является память.
                Stream memStream = new MemoryStream();
                // заголовок границы в байтах
                byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
                string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Dis name=\"{0}\";\r\n\r\n{1}";
                //nvc - коллекция параметров для месторасположения контента ИМЯ
                foreach (string key in nvc.Keys)
                {
                    string formitem = string.Format(formdataTemplate, key, nvc[key]);
                    byte[] formitembytes = Encoding.UTF8.GetBytes(formitem);
                    memStream.Write(formitembytes, 0, formitembytes.Length);
                }
                memStream.Write(boundarybytes, 0, boundarybytes.Length);
                string headerTemplate = "Content-Dis name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
                //Здесь происходит загрузка файла на отправку.
                for (int i = 0; i < files.Length; i++)
                {
                    //string header = string.Format(headerTemplate, "file" + i, files[i]);
                    //Заголовок отправляемого файла.
                    string header = string.Format(headerTemplate, "uplTheFile", files[i]);
                    //Конвертирует в байты.
                    byte[] headerbytes = Encoding.UTF8.GetBytes(header);
                    //Записывает в поток для отправки POST - сообщения.
                    memStream.Write(headerbytes, 0, headerbytes.Length);
                    //открывает и считывает в поток файл, необходимый для отправки.
                    FileStream fileStream = new FileStream(files[i], FileMode.Open,
                    FileAccess.Read);
                    byte[] buffer = new byte[1024];
                    int bytesRead = 0;
                    // пишет в поток для отправки POST - запроса
                    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        memStream.Write(buffer, 0, bytesRead);
                    }
                    // Записывает границу POST - сообщения.
                    memStream.Write(boundarybytes, 0, boundarybytes.Length);
                    //Закрываем поток файла.
                    fileStream.Close();
                }
                //Устанавливаем длину POST - запроса
                ReqLoad.ContentLength = memStream.Length;
                //Получает System.IO.Stream Объект, используемый для записи данных запроса.
                //System.IO.Stream, используемый для записи данных запроса.
                Stream requestStream = ReqLoad.GetRequestStream();

                memStream.Position = 0;
                byte[] tempBuffer = new byte[memStream.Length];
                //Считываем в tempBuffer из memStream (в нём POST-запрос) 
                memStream.Read(tempBuffer, 0, tempBuffer.Length);

                memStream.Close();
                //Записываем из tempBuffer в requestStream (в нём - POST - запрос)
                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                requestStream.Close();

                //Ждём ответ:
                //После отправки POST-запроса ждём ответ.
                WebResponse RespLoad = null;
                try
                {
                    RespLoad = ReqLoad.GetResponse();

                    Stream streamResp = RespLoad.GetResponseStream();
                    StreamReader readerResp = new StreamReader(streamResp);

                    string readerRespStr = readerResp.ReadToEnd();

                    RespLoad.Close();
                    ReqLoad = null;
                    RespLoad = null;
                }
                catch ()
                {
                   ReqLoad = null;
                    RespLoad = null;                
                }
            }

                    

     Вот у меня что-то не отсылает файл при помощи рассматриваемого мной метода. Можете сказать причины? Либо дать свой вариант кода. А то что-то всё время ошибку выдает "Время операции истекло".

    А слушаю я его вот так... 

      HttpListener listener = new HttpListener();
                listener.Prefixes.Add("http://10.4.3.11:8012/");
                listener.Start();
                HttpListenerContext context;
                while (true) //прослушиваем
                {
                    context = listener.GetContext();
                    HttpListenerRequest request = context.Request;
                    
                    Stream requestStream = request.InputStream;
                    SaveFile(context.Request.ContentEncoding, GetBoundary(context.Request.ContentType), context.Request.InputStream);
                }

    30 июля 2012 г. 12:25

Ответы

  • Наконец время появилось...Вот написал с нуля, стартовая отправная точка.

    namespace FileUploadClient
    {
      class Program
      {
        static void Main(string[] args)
        {
          string fileName = "Desert.jpg";
          string url = @"http://localhost:8080/ListenerTest/";
          Console.Write("Отправка файла на сервер...");
          UploadFilesToRemoteUrl(url, fileName);
    #if DEBUG
          Console.Read();
    #endif
        }
        public static void UploadFilesToRemoteUrl(string url, string fileName)
        {
          WebClient webClient = new WebClient();
          webClient.BaseAddress = url;
          webClient.Credentials = CredentialCache.DefaultCredentials;
    
          //Получаем объект имеющегося файла.
          FileInfo file = new FileInfo(fileName);
          //Получаем его расширение, чтобы отправить его на сервер.
          //При желании можно отправлять и полное имя, для этого нужно увеличить размер массива
          //и записать туда данные имени.
          string contentType = file.Extension;
    
          //Фиксированный размер этого массива нужен, чтобы точно знать на сервере
          //какое количество байт относится к типу, чтобы не повредить данные файла.
          byte[] contentTypeArray = new byte[20];
          byte[] contentTypeBytes = Encoding.ASCII.GetBytes(contentType);
    
          //Копируется массив с типами файла, остальное нули.
          Array.Copy(contentTypeBytes, contentTypeArray, contentTypeBytes.Length);
          
          //Читаем файл, пишем байты в массив.
          FileStream fileStream = file.OpenRead();
          byte[] fileBytes = new byte[fileStream.Length];
          fileStream.Read(fileBytes, 0, fileBytes.Length);
    
          //Создаём конечный массив байт,раширение файла + данные.
          byte[] uploadBytes = new byte[20 + fileBytes.Length];
          Array.Copy(contentTypeArray, uploadBytes, 20);
          Array.Copy(fileBytes, 0, uploadBytes, 20, fileBytes.Length);
    
          //Отправляем файл на сервер.
          webClient.UploadData(webClient.BaseAddress, uploadBytes);
    
          Console.Write("Файл" + fileName + "успешно отправлен.");
          webClient.Dispose();
    
        }
      }
    }
    namespace FileServer
    {
      class Program
      {
        static void Main(string[] args)
        {
          //Думаю этот кусок кода понятен.
          HttpListener listener = new HttpListener();
          listener.Prefixes.Add("http://localhost:8080/ListenerTest/");
          listener.Start();
          Console.WriteLine("Сервер запущен...\n");
    
          //Будем обрабатывать запросы асинхронно.
          IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
    
          //Чтобы консоль не закрылась.
          Console.ReadLine();
          //listener.Stop();
        }
        public static void ListenerCallback(IAsyncResult result)
        {
          //Берём результат возврата функции, получаем интересные нам объекты.
          HttpListener listener = (HttpListener)result.AsyncState;
          HttpListenerContext context = listener.EndGetContext(result);
          HttpListenerRequest request = context.Request;
    
          //Ето уже не нужно, в .Net 4 есть функция Stream.CopyTo() которой так не хватало,
          //начал писать, не дописав вспомнил.
          //System.IO.Stream body = request.InputStream;
          //System.Text.Encoding encoding = request.ContentEncoding;
          //System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
          MemoryStream memoryStream = new MemoryStream();
          request.InputStream.CopyTo(memoryStream);
          byte[] uploadedBytes = memoryStream.ToArray();
    
          //Размер 20 байт это наш контракт, получаем их.
          byte[] fileTypeBytes = new byte[20];
          Array.Copy(uploadedBytes, 0, fileTypeBytes, 0, 20);
    
          //Декодируем расширение, так как оно меньше 20 байт, обычно это 3 байта,
          //нули не декодируем.
          string fileType = Encoding.ASCII.GetString(fileTypeBytes.Where(b=>b != 0).ToArray());
    
          //Создаём новый файл, и пишем в него байты из потока.
          FileInfo file = new FileInfo("NewFile." + fileType);
          using (FileStream fileStream = file.OpenWrite())
          {
            //Первые 20байт принадлежат расширению.
            fileStream.Write(uploadedBytes, 20, uploadedBytes.Length - 20);
          }
          HttpListenerResponse response = context.Response;
          response.StatusCode = 200;
          string responseString = "OK";
          byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
          response.ContentLength64 = buffer.Length;
          System.IO.Stream output = response.OutputStream;
          output.Write(buffer, 0, buffer.Length);
          output.Close();
          //Тут также можно щаписывать всякие статистические данные касательно файла.
          Console.WriteLine("Файл упешно принят.\n");
        }
      }
    }

    Вот ссылка на готовый проект. Это хорошая база, для старта. Начните изучать и модернезировать его, так будет лучше. Лучше самому начь потихоньку писать разбираясь в коде, чем копировать непонятный код, и терять на этом много времени. Если, что помогу. А когда будет достаточно знаний, тогда и копи/пастить можно. 

    А Ваш проект, посмотрел. Он представляет склейку двух разных кодов, его надо доделать и дописывать, шлифовать, время для этого нужно. Клиентская часть этого проекта предназначена для отправки файлов на веб-сервер, который очень легко может их обработать. А чтобы корректно принять их с помощью HttpListener уже код который у Вас есть со StackOverflow нужно заменить, там только для получения одного файла.

    P.S. Времени свободного очень мало, работа - у сомого проекты "горят", и всё остальное, стараюсь как могу. Было бы оно у меня, только этим и занимался бы. Стараюсь помочь, ка и мне помогали когда то, когда я начинал.


    • Помечено в качестве ответа Sharpei Syroed 6 августа 2012 г. 4:02
    4 августа 2012 г. 7:03
    Модератор

Все ответы

  • Нашел http://s479.codeinspot.com/q/3210258

     У прогера такая же проблема.

    Я принимаю данные так - вот ссылка http://stackoverflow.com/questions/8466703/httplistener-and-file-upload 

    Помогите, кто нибудь. Что я не правильно делаю? Кучу литературы перерыл. Но контент(файл-картинка и txt файл) не грузится на сервер.  
    1 августа 2012 г. 5:34
  • А код клиента Вы писали или взяли готовый? А код на сервере который Вы привели или что со stackoverflow, котрый из них не работает?
    1 августа 2012 г. 7:30
    Модератор
  • А код клиента Вы писали или взяли готовый? А код на сервере который Вы привели или что со stackoverflow, котрый из них не работает?

    Взял готовый - вот отсюда  http://stackoverflow.com/questions/8466703/httplistener-and-file-upload 

    =============

    static void Main(string[] args)
    {
       
    HttpListener listener = new HttpListener();
        listener
    .Prefixes.Add("http://localhost:8080/ListenerTest/");
        listener
    .Start();

       
    HttpListenerContext context = listener.GetContext();

       
    SaveFile(context.Request.ContentEncoding, GetBoundary(context.Request.ContentType), context.Request.InputStream);

        context
    .Response.StatusCode = 200;
        context
    .Response.ContentType = "text/html";
        using
    (StreamWriter writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8))
            writer
    .WriteLine("File Uploaded");

        context
    .Response.Close();

        listener
    .Stop();

    }

    =============

     и немного изменил.

    Только что понял, что не работает SaveFile. В последнем цикле while 

    endPos = 0 всегда. А вот как проверить, почему так всегда происходит?

    Код SaveFile там же http://stackoverflow.com/questions/8466703/httplistener-and-file-upload

    Еще добавлю. Когда пишу вот так

                            Stream requestStream = request.InputStream;
                            StreamReader r = new StreamReader(requestStream, System.Text.Encoding.Default);                                              
                            string line;
                            while ((line = r.ReadLine()) != null)
                            {
                                Console.WriteLine(">>>>>"+line);
                            }

    в консоль все параметры выводятся... но естественно png или jpg файлы в виде лабуды всякой. Вот думаю может эту лабуду - конвертировать в png / jpg. Хотя задача заключается в том чтобы получить файл разного формата картинок.

    1 августа 2012 г. 8:34
  • Вот это я читал http://ru.wikipedia.org/wiki/HTTP

    Вот от сюда http://stackoverflow.com/questions/8466703/httplistener-and-file-upload метод SaveFile взял. 

    Я так понимаю смысл в том, чтобы согласовать метод отправки и метод принятия файла?


    2 августа 2012 г. 12:47
  • На первый взгляд всё усложнено, можно было и попроще, но нужно внимательно посмотреть. Пока времени нет, как буде сразу попробую.
    2 августа 2012 г. 12:50
    Модератор
  • Если посылаю 1 файл методом UploadFilesToRemoteUrl() на клиенте и вызываю один раз метод SaveFile на сервере, то не сохраняется ни один файл.

    Если посылаю 2 файла методом UploadFilesToRemoteUrl() на клиенте и вызываю два раза подряд метод SaveFile на сервере, то сохраняется второй(!!) файл.

    Мне кажется что с ума сошел. Помогите хотя бы ссылками,  а то боюсь алгоритм  самому не получится придумать.

    3 августа 2012 г. 8:09
  • Наконец время появилось...Вот написал с нуля, стартовая отправная точка.

    namespace FileUploadClient
    {
      class Program
      {
        static void Main(string[] args)
        {
          string fileName = "Desert.jpg";
          string url = @"http://localhost:8080/ListenerTest/";
          Console.Write("Отправка файла на сервер...");
          UploadFilesToRemoteUrl(url, fileName);
    #if DEBUG
          Console.Read();
    #endif
        }
        public static void UploadFilesToRemoteUrl(string url, string fileName)
        {
          WebClient webClient = new WebClient();
          webClient.BaseAddress = url;
          webClient.Credentials = CredentialCache.DefaultCredentials;
    
          //Получаем объект имеющегося файла.
          FileInfo file = new FileInfo(fileName);
          //Получаем его расширение, чтобы отправить его на сервер.
          //При желании можно отправлять и полное имя, для этого нужно увеличить размер массива
          //и записать туда данные имени.
          string contentType = file.Extension;
    
          //Фиксированный размер этого массива нужен, чтобы точно знать на сервере
          //какое количество байт относится к типу, чтобы не повредить данные файла.
          byte[] contentTypeArray = new byte[20];
          byte[] contentTypeBytes = Encoding.ASCII.GetBytes(contentType);
    
          //Копируется массив с типами файла, остальное нули.
          Array.Copy(contentTypeBytes, contentTypeArray, contentTypeBytes.Length);
          
          //Читаем файл, пишем байты в массив.
          FileStream fileStream = file.OpenRead();
          byte[] fileBytes = new byte[fileStream.Length];
          fileStream.Read(fileBytes, 0, fileBytes.Length);
    
          //Создаём конечный массив байт,раширение файла + данные.
          byte[] uploadBytes = new byte[20 + fileBytes.Length];
          Array.Copy(contentTypeArray, uploadBytes, 20);
          Array.Copy(fileBytes, 0, uploadBytes, 20, fileBytes.Length);
    
          //Отправляем файл на сервер.
          webClient.UploadData(webClient.BaseAddress, uploadBytes);
    
          Console.Write("Файл" + fileName + "успешно отправлен.");
          webClient.Dispose();
    
        }
      }
    }
    namespace FileServer
    {
      class Program
      {
        static void Main(string[] args)
        {
          //Думаю этот кусок кода понятен.
          HttpListener listener = new HttpListener();
          listener.Prefixes.Add("http://localhost:8080/ListenerTest/");
          listener.Start();
          Console.WriteLine("Сервер запущен...\n");
    
          //Будем обрабатывать запросы асинхронно.
          IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
    
          //Чтобы консоль не закрылась.
          Console.ReadLine();
          //listener.Stop();
        }
        public static void ListenerCallback(IAsyncResult result)
        {
          //Берём результат возврата функции, получаем интересные нам объекты.
          HttpListener listener = (HttpListener)result.AsyncState;
          HttpListenerContext context = listener.EndGetContext(result);
          HttpListenerRequest request = context.Request;
    
          //Ето уже не нужно, в .Net 4 есть функция Stream.CopyTo() которой так не хватало,
          //начал писать, не дописав вспомнил.
          //System.IO.Stream body = request.InputStream;
          //System.Text.Encoding encoding = request.ContentEncoding;
          //System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
          MemoryStream memoryStream = new MemoryStream();
          request.InputStream.CopyTo(memoryStream);
          byte[] uploadedBytes = memoryStream.ToArray();
    
          //Размер 20 байт это наш контракт, получаем их.
          byte[] fileTypeBytes = new byte[20];
          Array.Copy(uploadedBytes, 0, fileTypeBytes, 0, 20);
    
          //Декодируем расширение, так как оно меньше 20 байт, обычно это 3 байта,
          //нули не декодируем.
          string fileType = Encoding.ASCII.GetString(fileTypeBytes.Where(b=>b != 0).ToArray());
    
          //Создаём новый файл, и пишем в него байты из потока.
          FileInfo file = new FileInfo("NewFile." + fileType);
          using (FileStream fileStream = file.OpenWrite())
          {
            //Первые 20байт принадлежат расширению.
            fileStream.Write(uploadedBytes, 20, uploadedBytes.Length - 20);
          }
          HttpListenerResponse response = context.Response;
          response.StatusCode = 200;
          string responseString = "OK";
          byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
          response.ContentLength64 = buffer.Length;
          System.IO.Stream output = response.OutputStream;
          output.Write(buffer, 0, buffer.Length);
          output.Close();
          //Тут также можно щаписывать всякие статистические данные касательно файла.
          Console.WriteLine("Файл упешно принят.\n");
        }
      }
    }

    Вот ссылка на готовый проект. Это хорошая база, для старта. Начните изучать и модернезировать его, так будет лучше. Лучше самому начь потихоньку писать разбираясь в коде, чем копировать непонятный код, и терять на этом много времени. Если, что помогу. А когда будет достаточно знаний, тогда и копи/пастить можно. 

    А Ваш проект, посмотрел. Он представляет склейку двух разных кодов, его надо доделать и дописывать, шлифовать, время для этого нужно. Клиентская часть этого проекта предназначена для отправки файлов на веб-сервер, который очень легко может их обработать. А чтобы корректно принять их с помощью HttpListener уже код который у Вас есть со StackOverflow нужно заменить, там только для получения одного файла.

    P.S. Времени свободного очень мало, работа - у сомого проекты "горят", и всё остальное, стараюсь как могу. Было бы оно у меня, только этим и занимался бы. Стараюсь помочь, ка и мне помогали когда то, когда я начинал.


    • Помечено в качестве ответа Sharpei Syroed 6 августа 2012 г. 4:02
    4 августа 2012 г. 7:03
    Модератор
  • !!! (Не знаю вашего настоящего имени) Большое вам Человеческое спасибо. Буду юзать. В принципе я уже многое понял в коде.

    И еще  - здесь есть возможность как то оплатить помощь? Я бы с удовольствием отблагодарил посильной оплатой!!!

    5 августа 2012 г. 6:13
  • Yatajga,

    хотелось бы NameValueCollection еще передавать и парсить... Возможно ли это в вашем варианте ответа, если доработать его?
    6 августа 2012 г. 4:41
  • "И еще  - здесь есть возможность как то оплатить помощь? Я бы с удовольствием отблагодарил посильной оплатой!!!" - простого человеческого "Спасибо!" - достаточно, хотя некоторые и это забывают. Я тут не ради каких-либо материальных ценностей, а просто помогаю людям,такое тоже есть. Хотя, не скрою, для пополнения своих: багажа знаний и опыта, тоже.

    Новые вопросы, лучше задавать в новой теме, в следующий раз так и делайте. "хотелось бы NameValueCollection еще передавать и парсить... Возможно ли это в вашем варианте ответа, если доработать его?" - если Вы о передаче объектов, то ту нужен иже другой код. Нужно их сереализовывать при отправке, и десериализовывать при получении. Способов много, зависит от того каие именно объекты Вы хотите передать. Например для обычных можно использовать этот.

    6 августа 2012 г. 5:24
    Модератор