Форум программистов, компьютерный форум, киберфорум
Delphi: Сети
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.70/20: Рейтинг темы: голосов - 20, средняя оценка - 4.70
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
1

Отправка вайла в потоке idhttp

26.10.2012, 23:23. Показов 3956. Ответов 25
Метки нет (Все метки)

Ребят, загрузчик файлов на сервер через idhttp + idmultipartformdata работает на ура.

Но есть проблема - нужно сделать загрузку в потоке. Перерыл весь тындекс но внятной статьи про принципы создания и управления потоками так и не нашёл. Судь в том что б программа не зависала во время передачи файла. ПОмогите пожалуйста.

Вот рабочая функция нужно выполнить в потоке

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function TestIndy(url, FileName):string;
var
 PostStream     : TIdMultiPartFormDataStream;
 sMimeType      , response: String;
 sAttach:string;
 idhtp1 : TIdHTTP;
begin
 sAttach := FileName;
 sMimeType := 'application/cdp';
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 try
   PostStream :=   TIdMultiPartFormDataStream.Create;
   PostStream.Position:=0;
   PostStream.AddFile('main_file', sAttach, sMimeType);
   response := idhtp1.post(url,PostStream);
  finally
     PostStream.Free;
     idhtp1.Free;
  end;
  Result := response;
end;
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.10.2012, 23:23
Ответы с готовыми решениями:

Отправка картинки IdHTTP POST в потоке TMemoryStream
Получаю я картинку(капча) в поток(TMemoryStream) посредством запроса. Потом мне нужно эту картинку...

IdHTTP->Get в потоке и прогрессом
Есть код: TIdHTTP *HTTP = new TIdHTTP(NULL); if (HTTP) { try { HTTP->ConnectTimeout =...

idhttp в потоке получает пустой txt файл
Доброго времени суток. Пишу обновлялку для программы. Собственно, если код вставлен в FormCreate -...

Idhttp client, отправка запроса на сервер
Здравствуйте, уважаемые. Есть сервер на idhttpserver, сейчас пишу клиент на idhttp. Запрос серверу...

25
210 / 169 / 24
Регистрация: 24.04.2012
Сообщений: 615
27.10.2012, 00:20 2
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdHTTP, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdMultipartFormData;
 
type
  myhttp = class(TThread)
     url, FileName:string;
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;
 
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure myhttp.Execute;
var
 PostStream     : TIdMultiPartFormDataStream;
 sMimeType      , response: String;
 sAttach:string;
 idhtp1 : TIdHTTP;
begin
 sAttach := FileName;
 sMimeType := 'application/cdp';
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 try
   PostStream :=   TIdMultiPartFormDataStream.Create;
   PostStream.Position:=0;
   PostStream.AddFile('main_file', sAttach, sMimeType);
   response := idhtp1.post(url,PostStream);
  finally
     PostStream.Free;
     idhtp1.Free;
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  with myhttp.Create(true) do
  begin
    url:='-----------';
    FileName:='---------------';
    Resume;
  end;
end;
 
end.
1
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
27.10.2012, 18:38  [ТС] 3
Сейчас попробую. спасибо

Добавлено через 36 минут
Nutserus, Socket error #10061 вот на этой строчке
Delphi
1
response := idhtp1.post(url,PostStream);
А куда собственно функция ответ возвращает? Вот код нужной части юнита. Вызывается функция public_file с необходимыми параметрами. Она должна должна открывать поток (send_f) и получить из него тот самый загруженный url

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
unit Web;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdHTTP, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdMultipartFormData;
 
  type
  myhttp = class(TThread)
     url, FileName, kuids:string;
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;
 
function public_file(fname,kuids:string):string;
 
implementation
 
procedure myhttp.Execute;
var
 PostStream     : TIdMultiPartFormDataStream;
 sMimeType      , response: String;
 sAttach,kuids:string;
 idhtp1 : TIdHTTP;
begin
 sAttach := FileName;
 sMimeType := 'application/7z';
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 try
   PostStream :=   TIdMultiPartFormDataStream.Create;
   PostStream.Position:=0;
   PostStream.AddFile('main_file', sAttach, sMimeType);
   PostStream.AddFormField(UTF8Encode('main[row][0][file][file]'),UTF8Encode('main_file'));
   PostStream.AddFormField(UTF8Encode('main[row][0][comment]'),UTF8Encode(kuids));
   response := idhtp1.post(url,PostStream);
  finally
     PostStream.Free;
     idhtp1.Free;
  end;
end;
 
function mylink(kuids,link: string):string;
var
 response,guid: String;
 idhtp1 : TIdHTTP;
 ID:TGUID;
begin
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 CreateGuid(ID);
 kuids := StringReplace(kuids,'<','',[rfReplaceAll, rfIgnoreCase]);
 kuids := StringReplace(kuids,'>','',[rfReplaceAll, rfIgnoreCase]);
 guid := GUIDToString(ID);
 try
   response := idhtp1.Get('{путь к генератору ссылок}?guid='+guid+'&link='+link+'&kuids='+kuids);
  finally
     idhtp1.Free;
  end;
  Result := response;
end;
 
function send_f(url, fname, kuids:string):string;
begin
  with myhttp.Create(true) do begin
    url:=url;
    FileName:=fname;
    kuids:=kuids;
    Resume;
  end;
end;
 
function public_file(fname,kuids:string):string;
var i:Integer; tmp:string;
begin
  tmp := send_f('http://www.hd**********/', fname, kuids);
  i := Pos('http://www.hd**********/download/', tmp);
  Delete(tmp, 1, i-1);
  i := Pos('"', tmp);
  Delete(tmp, i, Length(tmp));
  tmp := mylink(kuids, tmp);
  Result := tmp;
end;
 
end.
Добавлено через 36 минут
Немного подкорректировал код, заметив совпадение имён переменных. Если вызываю из public_file функцию testindy то всё отлично работает. А если send_f - нет :-(

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
unit Web;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdHTTP, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdMultipartFormData;
 
  type
  myhttp = class(TThread)
     url1, FileName, kuids1:string;
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;
 
function public_file(fname,kuids:string):string;
 
implementation
 
procedure myhttp.Execute;
var
 PostStream     : TIdMultiPartFormDataStream;
 sMimeType      , response: String;
 sAttach:string;
 idhtp1 : TIdHTTP;
begin
 sAttach := FileName;
 sMimeType := 'application/7z';
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 try
   PostStream :=   TIdMultiPartFormDataStream.Create;
   PostStream.Position:=0;
   PostStream.AddFile('main_file', sAttach, sMimeType);
   PostStream.AddFormField(UTF8Encode('main[row][0][file][file]'),UTF8Encode('main_file'));
   PostStream.AddFormField(UTF8Encode('main[row][0][comment]'),UTF8Encode(kuids1));
   response := idhtp1.post(url1,PostStream);
  finally
     PostStream.Free;
     idhtp1.Free;
  end;
end;
 
function mylink(kuids,link: string):string;
var
 response,guid: String;
 idhtp1 : TIdHTTP;
 ID:TGUID;
begin
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 CreateGuid(ID);
 kuids := StringReplace(kuids,'<','',[rfReplaceAll, rfIgnoreCase]);
 kuids := StringReplace(kuids,'>','',[rfReplaceAll, rfIgnoreCase]);
 guid := GUIDToString(ID);
 try
   response := idhtp1.Get('{мой сервер тут}kuid/add/?guid='+guid+'&link='+link+'&kuids='+kuids);
  finally
     idhtp1.Free;
  end;
  Result := response;
end;
 
function send_f(url, fname, kuids:string):string;
begin
  with myhttp.Create(true) do begin
    url1:=url;
    FileName:=fname;
    kuids1:=kuids;
    Resume;
  end;
end;
 
function TestIndy(url, FileName, kuids: string):string;
var
 PostStream     : TIdMultiPartFormDataStream;
 sMimeType      , response: String;
 sAttach:string;
 idhtp1 : TIdHTTP;
begin
 sAttach := FileName;
 sMimeType := 'application/cdp';
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 try
   PostStream :=   TIdMultiPartFormDataStream.Create;
   PostStream.Position:=0;
   PostStream.AddFile('main_file', sAttach, sMimeType);
   PostStream.AddFormField(UTF8Encode('main[row][0][file][file]'),UTF8Encode('main_file'));
   PostStream.AddFormField(UTF8Encode('main[row][0][comment]'),UTF8Encode(kuids));
   response := idhtp1.post(url,PostStream);
  finally
     PostStream.Free;
     idhtp1.Free;
  end;
  Result := response;
end;
 
function public_file(fname,kuids:string):string;
var i:Integer; tmp:string;
begin
  tmp := send_f('http://www.hd**********/', fname, kuids);
  i := Pos('http://www.hd**********/download/', tmp);
  Delete(tmp, 1, i-1);
  i := Pos('"', tmp);
  Delete(tmp, i, Length(tmp));
    tmp := mylink(kuids, tmp);
    Result := tmp;
end;
 
end.
Добавлено через 10 минут
В общем вот что у меня получилось. Ни хрена не получилось
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
unit Web;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdHTTP, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdMultipartFormData;
 
  type
  myhttp = class(TThread)
     url1, FileName, kuids1:string;
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;
 
function public_file(fname,kuids:string):string;
 
implementation
 
procedure myhttp.Execute;
var
 PostStream     : TIdMultiPartFormDataStream;
 sMimeType      , response: String;
 sAttach:string;
 idhtp1 : TIdHTTP;
begin
 sAttach := FileName;
 sMimeType := 'application/7z';
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 try
   PostStream :=   TIdMultiPartFormDataStream.Create;
   PostStream.Position:=0;
   PostStream.AddFile('main_file', sAttach, sMimeType);
   PostStream.AddFormField(UTF8Encode('main[row][0][file][file]'),UTF8Encode('main_file'));
   PostStream.AddFormField(UTF8Encode('main[row][0][comment]'),UTF8Encode(kuids1));
   response := idhtp1.post(url1,PostStream);
  finally
     PostStream.Free;
     idhtp1.Free;
  end;
end;
 
function mylink(kuids,link: string):string;
var
 response,guid: String;
 idhtp1 : TIdHTTP;
 ID:TGUID;
begin
 idhtp1 := TIdHTTP.Create(nil);
 idhtp1.HandleRedirects := True;
 CreateGuid(ID);
 kuids := StringReplace(kuids,'<','',[rfReplaceAll, rfIgnoreCase]);
 kuids := StringReplace(kuids,'>','',[rfReplaceAll, rfIgnoreCase]);
 guid := GUIDToString(ID);
 try
   response := idhtp1.Get('{мой сервер тут}kuid/add/?guid='+guid+'&link='+link+'&kuids='+kuids);
  finally
     idhtp1.Free;
  end;
  Result := response;
end;
 
function send_f(url, fname, kuids:string):string;
begin
  with myhttp.Create(true) do begin
    url1:=url;
    FileName:=fname;
    kuids1:=kuids;
    Resume;
  end;
end;
 
function public_file(fname,kuids:string):string;
var i:Integer; tmp:string;
begin
  tmp := send_f('http://www.hd**********/', fname, kuids);
  i := Pos('http://www.hd**********/download/', tmp);
  Delete(tmp, 1, i-1);
  i := Pos('"', tmp);
  Delete(tmp, i, Length(tmp));
    tmp := mylink(kuids, tmp);
    Result := tmp;
end;
 
end.
Вызываю функцию public_file.
Сначала должен идти запрос на сервер через поток функцией send_f. Программа не зависает, но запрос по ходу не выполняется. Так как следующая за ней функция mylink, которая генерирует ссылку на мой сервер, но работает без потока, выполняется, и запрос на мой серв доходит, однако переменная link в него приходит пустая :-(
А при закрытии программы вообще вылазит ошибка сокета 10053 на этой строке. Но надо заметить, что вылазит она, если я закрываю программу только когда файл ещё явно не успел улететь на сервер. Если закрываю спустя допустим минуту, когда 500-килобайтовый файл 100% улетел - ошибки при закрытии нет.

Delphi
1
response := idhtp1.post(url1,PostStream);
И что это может значить..

Добавлено через 16 часов 38 минут
Блин, выручайте. Никак не могу с шайтан-потоками разобраться........
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
27.10.2012, 21:45 4
Разберись с блоками try..finally и try..except.
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
27.10.2012, 22:21  [ТС] 5
А что в них не так? С ними как раз таки всё вроде кошерно
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
27.10.2012, 22:41 6
Цитата Сообщение от asharikov Посмотреть сообщение
С ними как раз таки всё вроде кошерно
С ними-то как раз и некошерно.

Код
// в этот момент в PostStream мусор
try
   PostStream :=   TIdMultiPartFormDataStream.Create; // представь себе что при выполнении этой строки возникло исключение
..
  finally
     PostStream.Free; //Включай мозг - что за объект ты здесь уничтожаешь, если он не существует и в PostStream мусор ? Тут же схлопочешь AV-исключение по своей же вине)
..
  end;
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
27.10.2012, 22:54  [ТС] 7
хммм, убрал блок try fially end
Теперь ошибка сокета 10093 на освобождении:
Delphi
1
  PostStream.Free;
Блин я не фига не пойму почему
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
27.10.2012, 23:16 8
Цитата Сообщение от asharikov Посмотреть сообщение
убрал блок try fially end
Поставил, убрал, опять поствил ..
К чему эти эксперименты вслепую ?
Абстрагируйся, забудь на время про свою "ошибку сокета", включи мозг и подумай над тем что я тебе скаазл ..
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
27.10.2012, 23:51  [ТС] 9
Как мусор может быть в PostStream если я его не инициализировал?
Я ж говорю не силён в потоках.
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
27.10.2012, 23:53 10
Цитата Сообщение от asharikov Посмотреть сообщение
Как мусор может быть в PostStream если я его не инициализировал?
Потому и мусор что ты её не инициализировал.
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
27.10.2012, 23:57  [ТС] 11
Ты имеешь в виду конструктор писать для класса?
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
28.10.2012, 00:03 12
Цитата Сообщение от asharikov Посмотреть сообщение
Я ж говорю не силён в потоках
ПРичем здесь вообще потоки ?
Это азы - область памяти под локальные переменные подпрограмм выделяется в стеке, содержимое переменные generic-типов при этом не определено ("мусор" в них).

Добавлено через 4 минуты
Цитата Сообщение от asharikov Посмотреть сообщение
конструктор писать для класса?
Зачем его писать-то ?
Он уже есть. И в ходе его исполнения может возникнуть исключение, т.е. объект создан не будет. При этом объектной переменной PostStream значение присвоено естественно не будет, т.е. в ней как был так и останется мусор на момент входа в твой блок finally.
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
28.10.2012, 00:05  [ТС] 13
И какой в этой ситуации выход из положения?
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
28.10.2012, 00:05 14
Цитата Сообщение от asharikov Посмотреть сообщение
я же в var описал эту переменную
Ну описал. И что ?
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
28.10.2012, 00:10  [ТС] 15
Ну договаривай тогда до конца. Я не знаю что делать в этом случае поэтому и пришёл сюда
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
28.10.2012, 00:12 16
.. заняли ресурс ..
try
.. поработали с ресурсом ..
finally
.. безусловно освободили ресурс ..
end
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
28.10.2012, 00:20  [ТС] 17
Delphi
1
2
3
4
5
6
7
8
9
10
PostStream :=   TIdMultiPartFormDataStream.Create;
  try
   PostStream.Position:=0;
   PostStream.AddFile('main_file', sAttach, sMimeType);
   PostStream.AddFormField(UTF8Encode('main[row][0][file][file]'),UTF8Encode('main_file'));
   PostStream.AddFormField(UTF8Encode('main[row][0][comment]'),UTF8Encode(kuids1));
   response := idhtp1.post(url1,PostStream);
  finally
  idhtp1.Free;
  end;
Блин всё равно эта ошибка....
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
28.10.2012, 00:29 18
Так с ты еще с try..except не разобрался)

try
.. работаем с ресурсом ..
except
.. "гасим" потенциальное исключение при работе с ресурсом ..
end
0
0 / 0 / 0
Регистрация: 13.12.2010
Сообщений: 28
28.10.2012, 00:32  [ТС] 19
Ну так покажи на этом конкретном примере) Так разбираться легче будет

Принципы работы try except end и try finally end я знаю.
0
2646 / 2269 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
28.10.2012, 00:42 20
Код
try
  SomeObject := TSomeObjectClass.Create;
  try
    SomeObject.SomeMethod;
  finally
    SomeObject.Free;
  end;
except
end;
Добавлено через 4 минуты
Цитата Сообщение от asharikov Посмотреть сообщение
Судь в том что б программа не зависала во время передачи файла
Доп.поток тебе вообще не нужен.
Просто шлепни на форму IdAntifreeze.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.10.2012, 00:42

Отправка POST запроса компонентом IdHTTP
Здравствуйте! Решаю простенькую задачку! Есть файл index.php. Там описана форма, состоящая из...

Отправка почты в другом потоке
Народ, мне надо отправить почту в дугом потоке, чтобы програ не висла. С помощью компонентов...

Отправка данных по таймеру в отдельном потоке
Добрый день, интересует такая вещь, нужно сделать передачу файла с данными каждые 5 секунд. При...

Отправка запроса на сайт в новом потоке
Всем привет, не хватает знаний и видимо не могу осознать как решить свою проблему. Программа...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.