http post 数据到底怎么弄?(100分)

  • 主题发起人 主题发起人 CJ
  • 开始时间 开始时间
C

CJ

Unregistered / Unconfirmed
GUEST, unregistred user!
随便用INDY还是FASTNET,我FORM见下,我现在用STRINGLIST声称临时文件,用WEBBROWSER递交,可以。
但是用FASTNET/INDY的HTTP控件都不行。说有内容为空。

st.Add('<HTML>');
st.Add('<form name=f1 method="POST" action="pwd.asp">');
st.Add(' <td width="87%" height="25"><input type="text" name="userid" value="' + EditUser.Text + '" size="15"></td>');
st.Add(' <td width="87%" height="25"><font size="2"><input type="password" name="userpwd" value = "' + EditPass.Text + '" size="15"> </font> </td>');
st.Add(' <td width="87%" height="94" valign="top"><select size="12" name="zhuanye">');
st.Add(' <option selected value="'+ EditSpecification.Text + '">专升本:计算机科学与技术</option>');
st.Add(' </select> </td>');
st.Add(' <td width="87%" height="18"><input');
st.Add(' type="radio" value="r1" checked name="usertype"><font size="2"> 用户  </font><input');
st.Add(' type="radio" name="usertype" value="r2">管理员</td>');
st.Add(' size="2"> <input type="submit" value="确定" name="B1">  <input type="reset"');
st.Add(' value="放弃" name="B2">  <a href="http://olclass.shtvu.edu.cn/onlineclass1/zhuce_des.htm" target="_blank">网上注册</a> </font>');
st.Add('</form>');
st.Add('</HTML>');
 
学习~~~~~~~~~~~
 
有你这么弄得吗?
好久不见了,我现在在上海做项目,可能要1个多月。
st.Add('userid='+ UrlEncode(EditUser.Text) + '&userpwd=' + UrlEncode(EditPass.Text) + '&zhuanye='+UrlEncode(EditSpecification.Text)
+'&usertype=r1' + '&B1=确定')

每个表单域用形如 name=value 的方式,每个域之间用"&"隔开"
对 value 部分最好近用UrlEncode对源码进行编码,否则会造成解析中的歧义。
 
SeaSky啊,真是好久不见啊,我过两天就去北京了。
我现在是用WEBBROWSER.PERFORM...做的,所以,才加到STRINGLIST中。
我试过了,HTTP不是GET而是POST,所以不是在URL上加的,而是加到那个什么东西里(1下想不出来)可用这个方法也不成。
 
POST一样呀,POST部分的文本就是这么编码的呀. (找点协议跟踪的东东你就会发现了)
procedure Post("http://www.someurl.com/poster.asp", aTstring, outputResponestream);

到北京做什么?
有空msn: linxin@msn.com
 
var st : Tstring ;
outputResponestream : Tstream ;
begin
..
..
..
st.Add('userid='+ UrlEncode(EditUser.Text) + '&userpwd=' + UrlEncode(EditPass.Text) + '&zhuanye='+UrlEncode(EditSpecification.Text)
+'&usertype=r1' + '&B1=确定');
idhttp1.Post('http://www.someurl.com/poster.asp', st, outputResponestream);
 
这个函数我知道,可总是不成功的:(

MSN:CJCJC@ONLINE.SH.CN
 
前段时间用到get的时候,查资料写出这个,
如果还不能解决,你将 UrlEncode用getUTF8代替试下。
可能用到别的函数库,如果缺少,发在qq上发消息给我,把unit给你也行

UCS4 = Cardinal;
function TForm1.getUTF8(s: String): String;
var
i: integer;
begin
s:= WideStringToUTF8(s);
Result := '';
for i:=1 to length(s) do
begin
Result:=Result+'%'+inttohex(ord(s),2);
end;
end;

function WideStringToUTF8(S: WideString): AnsiString;

var
ch: UCS4;
L, J, T,
bytesToWrite: Word;
byteMask: UCS4;
byteMark: UCS4;

begin
if Length(S) = 0 then
begin
Result := '';
Exit;
end;

SetLength(Result, Length(S) * 6); // assume worst case
T := 1;
for J := 1 to Length(S) do
begin
byteMask := $BF;
byteMark := $80;

ch := UCS4(S[J]);

if ch < $80 then
bytesToWrite := 1
else
if ch < $800 then
bytesToWrite := 2
else
if ch < $10000 then
bytesToWrite := 3
else
if ch < $200000 then
bytesToWrite := 4
else
if ch < $4000000 then
bytesToWrite := 5
else
if ch <= MaximumUCS4 then
bytesToWrite := 6
else
begin
bytesToWrite := 2;
ch := ReplacementCharacter;
end;

for L := bytesToWrite downto 2 do
begin
Result[T + L - 1] := Char((ch or byteMark) and byteMask);
ch := ch shr 6;
end;
Result[T] := Char(ch or firstByteMark[bytesToWrite]);
Inc(T, bytesToWrite);
end;
SetLength(Result, T - 1); // assume worst case
end;

调用:
if edtAll.Text<>'' then
begin
All := trim(edtAll.Text);
All := getUTF8(All);
end;
 
还有可能就是你的HTTP request 头没有处理对,好像需要增加一个content-type 声明
为formed data (具体什么记不得了。)
但TCP跟踪一下就知道了。
 
找到了
Content-type: application/x-www-form-urlencoded
delphi :
IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded' ;
IdHTTP1.Request.ContentLength := lenght(st.text)

 
2 SeaSky,
D7中我在 Interface下uses IdURI,
,报告说:[Error] Unit1.pas(46): Undeclared identifier: 'UrlEncode'.
最后只有将IdURI.pas加入自己的Application,在Implementation部分 use一下.好痛苦的说.
请问知道解决办法么?

另外,你的帖子中:
var st : Tstring ;
应该是TStrings吧?


var
idURi : TIdURI;
Response : TStringStream ;
st : TStrings;
a : String;
begin
idUri := TidURI.Create();
a := idUri.URLEncode(Edit1.Text);
end;
 
这样不能post成功,
[red] idUri := TidURI.Create(); [/red]
会引发下面的异常:
idUri := TidURI.Create();function TIdURI.GetFullURI(
const AOptionalFileds: TIdURIOptionalFieldsSet): String;
Var
LURI: String;
begin
if Length(FProtocol) = 0 then
[red] raise EIdURIException.Create(RSURINoProto); [/red]
 
这次用D6测试
uses idglobal;

var
Responses : TStringStream ;
st : TStrings;
PostText : string;
begin
Responses := TStringStream.Create('');
PostText := 'HomeUrl='+UrlEncode(Edit1.text)+'&yourContent=' + UrlEncode(Edit2.text);
st := TStringList.Create;

st.Append(PostText);

try
IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded' ;
IdHTTP1.Request.ContentLength := length(st.text);
[red]idHttp1.Post('http://www.xxtax.gov.cn/delphi/guest.htm',st,Responses);[/red]
-----提交的时候出错,method 405 not allowed
finally
ResPonses.Free;
St.Free;
end;

 
2 SeaSky,
D7中不用增加 contenttype的声明
>>还有可能就是你的HTTP request 头没有处理对,好像需要增加一个content-type 声明
>>为formed data (具体什么记不得了。)

procedure TIdCustomHTTP.Post(AURL: string; const ASource: TStrings; const AResponseContent: TStream);
var
LParams: TStringStream;
begin
// Usual posting request have default ContentType is application/x-www-form-urlencoded
if (Request.ContentType = '') or (AnsiSameText(Request.ContentType, 'text/html')) then
Request.ContentType := 'application/x-www-form-urlencoded';

LParams := TStringStream.Create(SetRequestParams(ASource));
try
Post(AURL, LParams, AResponseContent);
finally
LParams.Free;
end;
end;
 
初步查到原因,'http://www.xxtax.gov.cn/delphi/guest.htm'
后缀名不能为.htm
 
直接将后缀名改为.asp
var
Responses : TStringStream ;
st : TStrings;
PostText : string;
begin
Responses := TStringStream.Create('');
//PostText := 'HomeUrl='+UrlEncode(Edit1.text);
PostText := 'HomeUrl='+Edit1.text+'&yourContent=' + Edit2.text;
st := TStringList.Create;
st.Add(PostText);
try try
IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded' ;
IdHTTP1.Request.ContentLength := length(st.text);
idHttp1.Post('http://169.12.2.27/qian/guest.asp', st, Responses);
Memo1.Text := Responses.DataString;
Except
on E: Exception do
showmessage('Error encountered during POST: ' + E.Message);
end;
finally
ResPonses.Free;
St.Free;
end;

Memo1中显示Responses的DataString如下(未能post上数据):
<HTML>
<HEAD>
<TITLE>资源共享网站列表</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</HEAD>

<BODY bgcolor="a4d5ff">

<form method="post" action="../myWebServer.exe/form" >
<P> <LABLE for "HomePage" > 资源共享网站首页地址:</LABLE>
<P><LABLE for "HomePage" ></LABLE>
<td class="row2"><input type="text" style="width:200px" name="HomeUrl" size="25" maxlength="255" id="HomePage" value="" /></td>

<P><BR>
<Lable > 共享内容简介:</LABLE>
<P><Lable ></LABLE>
<input type="text" style="width:200px" name="yourContent" size="25" maxlength="255" id="myContent" value="" />
<P> <BR>
<tr>
<th>  </th>
<th> </th>
<p>
<input type="submit" name="pushbutton" value=" Submit ">
<input type="reset" name="resetButton" value=" Clear ">
</P>
</form>
</body>
</HTML>
 
在HTTP发送时, Post是将数据加入到消息体中, 也就是Context部分中, 它不会出现在URL部分(Get是这样),
因而与URL编码是无关的. Post内文的编码是由IE缺省编码负责的, 可以不用管. 如果你真的是自己来处理,
可以往下面看. :)

form表单有一个属性, 是enctype, 它用于给Context部分的内容编码或表明内容的类型, 如果你要发送超
大的文件(比如大于48K, 注意, 是48K, 而不是64K), 你就需要用多节数据, 这种情况下, 一个简单的表单
应该写成这样:
-----------------------------------------------------------------
<form method="post" enctype="multipart/form-data"
action="http://192.168.0.114/Scripts/DBCenter.dll/add">
<input type="file" name="aFile"><br><br>
<input type="submit" value="发送文件">
<input type="reset" value="取消发送">
</form>
-----------------------------------------------------------------
但是, 这是针对是大数据块, 或文件的, CJ的这个表单没有这样的问题. 所以也与enctype无关.

你的这个错误信息提示是"有内容为空", 那么, 应该是你的表单中有一项或多项的值传到服务器
上时, 是没有值的. 我仔细地查了一下, 这个表单发到服务器上的数据会是这个样子:
userid=abc&userpwd=def&zhuanye=ghi&usertype=r1&B1=%C8%B7%B6%A8
这个数据其实还是正常的, 表单中"放弃"(B2)按钮的值不会被发到服务器上, 这是IE内定的.

所以, 我认为, 这不是你的表单的问题.(你的表单中有些错误, 但不影响这个结果)
这也是你"用WEBBROWSER递交,可以"的原因.

而且Indy等将HTML加入(add)的话, 其实也是最终返回给客户端的WebBrowser处理的, 这个是
一样的. 所以还是与HTML无关.
我想, 这与你操作Indy的那段代码有关系, 也就是说, 你用Indy返回这个表单到客户端的浏览
器, 其中你有用了一个中介, 就是"TStringList", 我在想, 你是不是这段代码写的有问题, 使
Indy的返回的Respones.Context的内容为空, 从而导致上述的错误. 或者类似的原因?

第二点, 是我写完上述内容后才发现的:
TIdHttp.Post()这个方法我没有看过, 我向来不用INDY的. 但是, SeaSkey给出了这个过程的声明:
procedure Post("http://www.someurl.com/poster.asp", aTstring, outputResponestream);
那么, 我想, 你们是不是理解错了?
其实, 一个HttpClient的这两个参数表通常是这样用的:
aTString : 用来提供一个值对, 表示将要Post的数据
outputResponestream : 用来提供一个Context的全文, 表明Post流的Memory.
那么, 什么样的"值对"才是Indy所理解的呢? 其实应该是很简单的, 就是标准的TStringList的用法:
Name=value
这样的值对就可以了.
而不需要象CJ提供的代码那样, 连HTML都放了进去. 那样反倒是错的了. 你想, Indy会从aTString
中去分析一遍HTML的语法吗? ---- 不会吧!
此外, 我想, 如果不通过流来Post, 这个outputResponestream参数是不是可以设成nil?

因此, 我想应该这样用才合理啊:
begin
...
st.Add('userid=abc');
st.Add('zhuanye=ghi');
st.Add('usertype=r1');
idhttp1.Post('http://www.someurl.com/poster.asp', st, nil);
//或
//idhttp1.Post('http://www.someurl.com/poster.asp', st, outputResponestream);
...
end;
 
给以给一个地址供大家测试:
http://www.xxtax.gov.cn/delphi/guest.asp

asp页面的代码:
<HTML>
<HEAD>
<TITLE>资源共享网站列表</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</HEAD>

<BODY bgcolor="a4d5ff">

<form method="post" action="myWebServer.exe/form" >
<P> <LABLE for "HomePage" > 资源共享网站首页地址:</LABLE>
<P><LABLE for "HomePage" ></LABLE>
<td class="row2"><input type="text" style="width:200px" name="HomeUrl" size="25" maxlength="255" id="HomePage" value="" /></td>

<P><BR>
<Lable > 共享内容简介:</LABLE>
<P><Lable ></LABLE>
<TEXTAREA wrap=logical name="yourContent" ROWS=6 COLS=60 value="This is a test"Swansea, IL></TEXTAREA>
<P> <BR>
<tr>
<th>  </th>
<th> </th>
<p>
<input type="submit" name="pushbutton" value=" Submit ">
<input type="reset" name="resetButton" value=" Clear ">
</P>
</form>
</body>
</HTML>
 
indy程序是否能post上去
可以通过如下网址查看:
http://www.xxtax.gov.cn/delphi/mywebserver.exe/entries
 
测试,仍未能post。

今晚别过诸位,先去沐浴更衣,然后回家休息几天。

这个程序比较重要,几乎是最后的问题了,2天多的时间无结果。
国庆回来仍然不能 post只能嵌入TwebBrowser了[:(]

aimin你用ics?
 
后退
顶部