Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.04.2012, 00:30   #1
Vladimirok
 
Регистрация: 21.10.2011
Сообщений: 3
По умолчанию Отправка файла на HTTP сервер POST запросом на WinSock

Код:
function SendPostFileReguest(url, post_data: String; post_filename: String; filename: String): TWinSocksResponse;
var
  WSAData: TWSAData;
  ErrorCode: Integer;
  FSocket: TSocket;
  HostEnt: PHostEnt;
  InAddr: TInAddr;
  FAddr: TSockAddrIn;
  Blocking: Longint;
  arg: Integer;
  request: AnsiString;
  savetickcount: Cardinal;
  c: AnsiChar;
  response: AnsiString;
  response_data: AnsiString;
  Headers: Boolean;
  RecivedBytes: Integer;
  host: PAnsiChar;
  boundary: AnsiString;
  boundary_end: AnsiString;
  FileData: TMemoryStream;
  FileDataSended: Integer;
  FBuf: Array [0..4095] of AnsiChar;
begin
  Result.Headers := '';
  Result.Content := '';
  if not FileExists(filename) then
  begin
    Exception.Create('file not exist: (' + filename + ')');
  end;
  FileData := TMemoryStream.Create;
  FileData.LoadFromFile(filename);
  FileData.Position := 0;
  ErrorCode := WSAStartup($0101, WSAData);
  if ErrorCode <> 0 then raise Exception.Create('WSAStartup');
  try
    FSocket := socket(PF_INET, SOCK_STREAM, 0);
    if FSocket = INVALID_SOCKET then raise Exception.Create('socket');
    host := PAnsiChar(AnsiString(Self.fGetHostName(url)));
    HostEnt := gethostbyname(host);
    FillChar(InAddr, SizeOf(InAddr), 0);
    if HostEnt<>nil then
    begin
      InAddr.S_un_b.s_b1 := HostEnt^.h_addr^[0];
      InAddr.S_un_b.s_b2 := HostEnt^.h_addr^[1];
      InAddr.S_un_b.s_b3 := HostEnt^.h_addr^[2];
      InAddr.S_un_b.s_b4 := HostEnt^.h_addr^[3];
    end else raise Exception.Create('gethostbyname: (' + Self.fGetHostName(url) + ')');
    FAddr.sin_family := PF_INET;
    FAddr.sin_addr := InAddr;
    FAddr.sin_port := htons(80);
    Blocking := 0;
    ioctlsocket(FSocket, FIONBIO, Blocking);
    ErrorCode := connect(FSocket, FAddr, SizeOf(FAddr));
    if ErrorCode <> 0 then raise Exception.Create('connect');
    try
      boundary := AnsiString(inttohex(random(65535), 4)) + AnsiString(inttohex(random(65535), 4)) + AnsiString(inttohex(random(65535), 4));
      request := 'POST ' + url + ' HTTP/1.1' + #13#10 +
        'Host: ' + Self.fGetHostName(url) + #13#10 +
        'Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0' + #13#10 +
        'Accept-Language: ru,en-us;q=0.7,en;q=0.3' + #13#10 +
        'Connection: close' + #13#10 +
        'Content-Type: multipart/form-data; boundary=' + boundary + #13#10 +
        'Content-Length: ' + IntToStr(FileData.Size) + #13#10 +
        #13#10 +
        '--' + boundary + #13#10 +
        'Content-Disposition: form-data; name="' + post_filename + '"; filename="' + filename + '"' + #13#10 + #13#10;

      boundary_end := #13#10 + '--' + boundary + '--' + #13#10;
      //Отправляем хедеры
      send(FSocket, Pointer(request)^, Length(request), 0);
      //Testing...
      //send(FSocket, FileData.Memory^, FileData.Size, 0); //Файл приходит с ошибкой
      send(FSocket, Pointer(FileData)^, FileData.Size, 0); //Приходит битый файл
      //Отправляем файл по частям... сервер после этого не отвечает, и файл не приходит...
      //FileDataSended := 0;
      {repeat
        FileData.Read(FBuf, 4096);
        send(FSocket, Pointer(AnsiString(FBuf))^, 4096, 0);
        FileDataSended := FileDataSended + 4096;
      until FileDataSended <= FileData.Size;}
      //Оповещаем об окончании
      send(FSocket, Pointer(boundary_end)^, Length(boundary_end), 0);
      //Ждем ответа от сервера
      savetickcount := GetTickCount;
      response := '';
      response_data := '';
      Headers := true;
      RecivedBytes := 2;
      while Integer(GetTickCount - savetickcount) < (Self.fTimeout * 1000) do
      begin
        if(ioctlsocket(FSocket, FIONREAD, arg)<0) then Exit;
        if arg > 0 then
        begin
          RecivedBytes := recv(FSocket, c, 1, 0);
          if RecivedBytes = SOCKET_ERROR then break;
          if Headers then
          begin
            response := response + c;
          end
            else
          begin
            response_data := response_data + c;
          end;
          if (Length(response)>=4) and (Copy(response, Length(response)-3, 4)=#13#10#13#10) then
          begin
            if Headers then
            begin
              response := Copy(response, 1, Length(response)-4);
              Headers := false;
            end;
          end;
        end
          else
        begin
          Sleep(10);
        end;
        if RecivedBytes <= 1 then
        begin
          if arg <= 0 then Break;
        end;
      end;
      Result.Headers := Result.Headers + AnsiString(response);
      Result.Content := Result.Content + response_data;
    finally
      ErrorCode:=closesocket(FSocket);
      if ErrorCode<>0 then raise Exception.Create('closesocket');
    end;
  finally
    ErrorCode := WSACleanup;
    if ErrorCode<>0 then raise Exception.Create('WSACleanup');
  end;
end;
Vladimirok вне форума Ответить с цитированием
Старый 13.04.2012, 00:32   #2
Vladimirok
 
Регистрация: 21.10.2011
Сообщений: 3
По умолчанию

Извините, вопрос вместе с функцией не влез:

Добрый вечер, нужна ваша помощь. Пишу функцию для отправки файла на HTTP сервер POST запросом на WinSock. Дело в том что файл отправляется но только первые например 94324 байтов. Сам запрос отправляю себе на PHP скрипт. Оригинальный размер файла: 490358 байт.

Наверное нужно отправлять файл по частям по несколько байт, пытался, не получается, сервер не отвечает... Планирую еще вывести ProgressBar процесса отправки файла. Собственно вопрос, как отправить файл по частям с использованием TMemoryStream что бы юникод все не портил?

Можно как то отправить в соккет напрямую части из TMemoryStream что бы их не выдергивать сначала в AnsiChar или Char массив?

Код:
type
  TWinSocksResponse = record
    Headers: AnsiString;
    Content: AnsiString;
  end;
Vladimirok вне форума Ответить с цитированием
Старый 14.04.2012, 06:26   #3
Vladimirok
 
Регистрация: 21.10.2011
Сообщений: 3
Смех Все решилось...

Большое спасибо... все решилось само собой. Помог гугл и снифер.
Vladimirok вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
http server,http сервер, проблемы с post реализация на java snajper_ro Общие вопросы по Java, Java SE, Kotlin 1 23.10.2011 14:25
Поиск файла в подкаталогах и отправка на сервер Ёжик в тумане Общие вопросы Delphi 1 20.07.2011 11:17
Отправка файла POST-запросом на PHP-скрипт... ActiveX Работа с сетью в Delphi 7 20.07.2009 16:54
Отправка файла на сервер kirill555 PHP 8 21.12.2007 12:51