悲催的idhttpServer. Get 浏览网页 编码问题.明明网页中有chaset,但中文仍然显示为乱码. 必须在 ContentType中指定 chaset, AResponseInfo.CharSet 设置无效??? contentType := GetMimeTypeFromFile(LocalDoc); if LeftStr(ContentType, 4) = 'text' then begin ContentType := ContentType + '; charset=gb2312'; end; AResponseInfo.ContentType := contentType; AResponseInfo.ContentText 指定为含有中文的字符串,会显示乱码. 用流. AResponseInfo.ResponseNo := 404; AResponseInfo.ContentType := 'text/plain' + '; charset=gb2312'; //乱码须用流的形式 {memoryStream:=TMemoryStream.Create; s:='找不到' + ARequestInfo.Document; memorystream.write(PAnsichar(s)^,length(s)); AResponseInfo.ContentStream := memorystream; } AResponseInfo.ContentText := '<html>' + #13#10 + '<body>' + #13#10 + 'Page not found:<br>' + #13#10 + '<b>' + ARequestInfo.Document + '</b>' + #13#10 + '</body>' + #13#10 + '</html>'; 对于存在的文件,用 AResponseInfo.ServeFile(AContext, rPage)来试试看.可能可以避免乱码,未实验,估计可行? procedure TfrmMain.ServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var rPage : String; begin Log('Serving: ' + ARequestInfo.Document + ' to ' + AContext.Connection.Socket.Host, clBlue); if (ARequestInfo.Document <> '') and (ARequestInfo.Document <> '/') and (ARequestInfo.Document <> '\') then rPage := Copy(ARequestInfo.Document, 2, Length(ARequestInfo.Document)) else rPage := 'Index.htm'; rPage := StringReplace(rPage, '/', '\',[rfReplaceAll, rfIgnoreCase]); rPage := IncludeTrailingBackslash(edServerRoot.Text) + rPage; if FileExists(rPage) then AResponseInfo.ServeFile(AContext, rPage) else AResponseInfo.ContentText := '<H1>ERROR</H1>File not found: '+ARequestInfo.Document; end; Post上传文件. procedure TForm1.IdHTTPServerCreatePostStream(AContext: TIdContext; AHeaders: TIdHeaderList; var VPostStream: TStream); begin //VPostStream:=TFileStream.Create('c:\1111111',fmCreate); //会包含所有信息,不仅仅上传的文件,还有http 协议信息 VPostStream := TMemoryStream.Create; end; procedure TForm1.IdHTTPServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var LocalDoc: string; ByteSent: Cardinal; ResultFile: TFileStream; memoryStream: TMemoryStream; contentType: string; s: String; Decoder, NewDecoder: TIdMessageDecoder; DestStream: TStream; IdPostStream, IdDestStream: TStream; //TIdStreamVcl ; MsgEnd: Boolean; Stream: TMemoryStream; procedure DecodeFormData(const Header: string; ASourceStream: TStream); var MsgEnd: Boolean; Decoder: TIdMessageDecoder; Tmp: string; Dest: TMemoryStream; begin MsgEnd := False; Decoder := TIdMessageDecoderMIME.Create(nil); try Decoder.SourceStream := ASourceStream; Decoder.FreeSourceStream := False; TIdMessageDecoderMIME(Decoder).MIMEBoundary := Decoder.ReadLn; //Decoder.ReadLn; repeat Decoder.ReadHeader; {case Decoder.PartType of mcptUnknown: raise Exception('Unknown form data detected'); mcptText: begin Tmp := Decoder.Headers.Values['Content-Type']; Dest := TMemoryStream.Create; try Decoder := Decoder.ReadBody(Dest, MsgEnd); if AnsiSameText(Fetch(Tmp, ';'), 'multipart/mixed') then DecodeFormData(Tmp, Dest) else // use Dest as needed... finally FreeAndNil(Dest); end; end; mcptAttachment: } begin Tmp := ExtractFileName(Decoder.FileName); if Tmp <> '' then Tmp := ExtractFilePath(Application.ExeName) + 'web\upload\'+Tmp else Tmp := MakeTempFilename('c:\temp\'); Dest := TMemoryStream.Create;//TFileStream.Create(Tmp, fmCreate); try NewDecoder := Decoder.ReadBody(Dest, MsgEnd); ///////yu add begin if NewDecoder <>nil then begin NewDecoder.SourceStream := ARequestInfo.PostStream; //yu NewDecoder.FreeSourceStream := False; //yu TIdMessageDecoderMIME(NewDecoder).MIMEBoundary := TIdMessageDecoderMIME(Decoder).MIMEBoundary ; end; if (Decoder <>nil) and(Decoder.Filename<>'') then Dest.SaveToFile(Tmp); ///////////yu add end Decoder.Free; Decoder := NewDecoder; finally FreeAndNil(Dest); end; end; //end; until (Decoder = nil) or MsgEnd; finally FreeAndNil(Decoder); end; end; begin LocalDoc := ExpandFileName(Edit1.Text + ARequestInfo.Document); if LocalDoc[Length(LocalDoc)] = '\' then Delete(LocalDoc, Length(LocalDoc), 1); if not FileExists(LocalDoc) and DirectoryExists(LocalDoc) then if FileExists(ExpandFileName(LocalDoc + '/index.html')) then LocalDoc := ExpandFileName(LocalDoc + '/index.html') else if FileExists(ExpandFileName(LocalDoc + '/index.htm')) then LocalDoc := ExpandFileName(LocalDoc + '/index.htm'); S := ARequestInfo.ContentType; if AnsiSameText(Fetch(S, ';'), 'multipart/form-data') then begin DecodeFormData(S, ARequestInfo.PostStream) ; end else // use request data as needed... if FileExists(LocalDoc) then begin if AnsiSameText(Copy(LocalDoc, 1, Length(edit1.text)), Edit1.Text) then begin ResultFile := TFileStream.create(LocalDoc, fmOpenRead or fmShareDenyWrite); try AResponseInfo.ResponseNo := 200; contentType := GetMimeTypeFromFile(LocalDoc); if LeftStr(ContentType, 4) = 'text' then begin ContentType := ContentType + '; charset=gb2312'; end; AResponseInfo.ContentType := contentType; AResponseInfo.ContentLength := ResultFile.Size; AResponseInfo.ContentStream := ResultFile; except ResultFile.Free; // We must free this file since it won 't be done by the web server component end; //下载文件 //ByteSent := AResponseInfo.ServeFile(AContext, LocalDoc); end; end else begin AResponseInfo.ResponseNo := 404; AResponseInfo.ContentType := 'text/plain' + '; charset=gb2312'; //乱码须用流的形式 {memoryStream:=TMemoryStream.Create; s:='找不到' + ARequestInfo.Document; memorystream.write(PAnsichar(s)^,length(s)); AResponseInfo.ContentStream := memorystream; } AResponseInfo.ContentText := '<html>' + #13#10 + '<body>' + #13#10 + 'Page not found:<br>' + #13#10 + '<b>' + ARequestInfo.Document + '</b>' + #13#10 + '</body>' + #13#10 + '</html>'; end; Memo1.Lines.Add(AReQuestInfo.Document); end; TIdMessageDecoderMIME.ReadBody 跟踪发现 //不大明白为啥要多加'--' if MIMEBoundary <> '' then begin BoundaryStart := '--' + MIMEBoundary; {Do not Localize} BoundaryEnd := BoundaryStart + '--'; {Do not Localize} end; 实际上传文件测试发现,发送的数据流中 没有多加的'--'.多此一举?? if IsBinaryContentTransferEncoding then begin //For binary, need EOL because the default LF causes spurious CRs in the output... LLine := ReadLnRFC(VMsgEnd, EOL, '.', Indy8BitEncoding); //do not localize end 上传rar文件测试,发现rar文件中的单个的#10, #13字符, 全部被替换成了#13#10两个字符, 结果文件变大了,rar文件也无法打开. 明明已经说了IsBinaryContentTransferEncoding, 还要多此一举. 搞了一天,上传也没搞好. 要不自己处理post收到的数据,不用 Decoder := Decoder.ReadBody(Dest, MsgEnd); idhhtp 阻塞式.可设置为非阻塞式 ICS非阻塞式 使用ICS V8 Gold. 编译 WebDemos下的OverbyteIcsWebServ 启动OverbyteIcsWebServ.exe 访问http://localhost/formupload.html 上传正常. |
|