![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Upload и IdHTTPServer
sairus © (2007-02-07 21:55:00)вопрос собственно не совсем к делфи относится, а к С++ Builder. Но они ведь почти родсвенники...
Так значит так... Мне бы надо организовать возможность загрузки файлов на удаленную машину, но клиент это должен дклать через веб-браузер... Нашел один я код на делфи, думаю он рабочий, но вот при пересройку его на Builder возникли проблемы...
procedure TForm1.ServerCommandGet(AThread: TIdPeerThread;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
Var PostedFile:TMemoryStream;
begin
If ARequestInfo.Document='/' Then begin
With AResponseInfo do begin
ContentText:=HtmlForm;
WriteContent;
end;
end else if ARequestInfo.Document='/upload/' then begin
PostedFile:=TMemoryStream.Create;
Try
Try
PostedFile.LoadFromStream(ARequestInfo.PostStream);
PostedFile.SaveToFile('.\'+(DateToStr(now)+' '+TimeToStr(now)+' '+AThread.Connection.Socket.Binding.PeerIP));
With AResponseInfo do begin
ContentText:=HtmlForm('Upload Successful!');
WriteContent;
end;
except
With AResponseInfo do begin
ContentText:=HTMLForm('Upload Error!');
WriteContent;
end;
end;
finally
PostedFile.Free;
end;
end;
end;
Проблема в том, что в компоненте IdHTTPServer Builder'а нету метода ARequestInfo.PostStream.
Вопрос: как то еще можно было бы переделать этот вот код, ну чтобы ARequestInfo.PostStream не использовался....
Я вот долго мучился с AThread.Connection.ReadStream(...)
Этим воспользоваться можно???- у меня ничего не выходит...
Подскажите пожалуйста, ответ на вопрос долго ищу, пока результат нулевой...
Спасибо.
SlymRO (2007-02-09 09:32:00) [1]Модуль... не пинайте за баги... as is
unit MultipartFormData;
interface
uses
Classes, IdGlobal, IdException, IdResourceStringsProtocols, IdStreamVCL, SysUtils, IdTStrings,IdCustomHTTPServer;
const
sContentTypeFormData = 'multipart/form-data; boundary='; {do not localize}
sContentTypeOctetStream = 'application/octet-stream'; {do not localize}
crlf = #13#10;
sContentDisposition = 'Content-Disposition: form-data; name="%s"'; {do not localize}
sFileNamePlaceHolder = '; filename="%s"'; {do not localize}
sContentTypePlaceHolder = 'Content-Type: %s'; {do not localize}
sContentTransferEncoding = 'Content-Transfer-Encoding: binary'; {do not localize}
type
TFormDataField = class(TCollectionItem)
private
FFileName: string;
FContentType: string;
FFieldName: string;
FData: TStringStream;
//FHeaders:TStrings;
procedure SetContentType(const Value: string);
function GetFieldValue: string;
procedure SetFieldValue(const Value: string);
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
//property Headers:TStrings read FHeaders;
property ContentType: string read FContentType write SetContentType;
property FieldName: string read FFieldName write FFieldName;
property FileName: string read FFileName write FFileName;
property Data: TStringStream read FData;
property FieldValue: string read GetFieldValue write SetFieldValue;
end;
TFormDataFields = class(TCollection)
private
FBoundary: string;
function GetFormDataField(AIndex: Integer): TFormDataField;
function GetFormDataFieldByName(const AName:string): TFormDataField;
function GetItemIndex(const AName: string): integer;
public
constructor Create;
function Add: TFormDataField;
property Items[AIndex: Integer]: TFormDataField read GetFormDataField;
property ItemIndex[const AName:string]: integer read GetItemIndex;
property ItemByName[const AName:string]: TFormDataField read GetFormDataFieldByName;
property Boundary: string read FBoundary write FBoundary;
end;
procedure ParseRequest(RequestInfo: TIdHTTPRequestInfo;FormDataFields:TFormDataFields);
implementation
uses IdGlobalProtocols;
procedure ParseRequest(RequestInfo: TIdHTTPRequestInfo;FormDataFields:TFormDataFields);
var
Strings:TStringList;
UnparsedParams,Part,S:string;
Field: TFormDataField;
begin
if Pos('multipart/form-data',RequestInfo.ContentType)=0 then exit;
Strings:=TStringList.Create;
try
Strings.Delimiter:=';';
Strings.DelimitedText:=RequestInfo.ContentType;
FormDataFields.Boundary:=Strings.Values['boundary'];
if Length(FormDataFields.Boundary)=0 then
raise Exception.Create('No multipart boundary');
UnparsedParams:=RequestInfo.UnparsedParams;
Fetch(UnparsedParams,'--'+FormDataFields.Boundary);
while Length(UnparsedParams)>0 do
begin
Fetch(UnparsedParams,#13#10);
Part:=Fetch(UnparsedParams,#13#10'--'+FormDataFields.Boundary);
if Length(Part)=0 then continue;
Strings.NameValueSeparator:=':';
Strings.Text:='';
repeat
s:=Fetch(Part,#13#10);
if Length(s)=0 then Break;
Strings.Add(s)
until False;
Field:=FormDataFields.Add;
S:=Strings.Values['Content-Disposition'];
Fetch(S,'name=');
Field.FieldName:=AnsiDequotedStr(Fetch(S,';'),'"');
S:=Strings.Values['Content-Disposition'];
Fetch(S,'filename=');
Field.FileName:=AnsiDequotedStr(Fetch(S,';'),'"');
Field.ContentType:=Strings.Values['Content-Type'];
Field.FieldValue:=Part;
end;
finally
Strings.Free;
end;
end;
{ TFormDataFields }
function TFormDataFields.Add: TFormDataField;
begin
Result := TFormDataField(inherited Add);
end;
constructor TFormDataFields.Create();
begin
inherited Create(TFormDataField);
end;
function TFormDataFields.GetFormDataField(AIndex: Integer): TFormDataField;
begin
Result := TFormDataField(inherited Items[AIndex]);
end;
function TFormDataFields.GetItemIndex(const AName: string): integer;
begin
for result:=0 to Count-1 do
if Items[result].FieldName=AName then
exit;
result:=-1;
end;
function TFormDataFields.GetFormDataFieldByName(const AName:string): TFormDataField;
var i:integer;
begin
i:=ItemIndex[AName];
if i<0 then
raise Exception.CreateFmt('Item by name %s not finded',[AName]);
result:=Items[i];
end;
{ TFormDataField }
constructor TFormDataField.Create(Collection: TCollection);
begin
inherited Create(Collection);
//FHeaders:=TStringList.Create;
FData := TStringStream.Create('');
FFileName := '';
FFieldName := '';
FContentType := '';
end;
destructor TFormDataField.Destroy;
begin
FData.Free;
//FHeaders.Free;
inherited;
end;
procedure TFormDataField.SetContentType(const Value: string);
begin
if Length(Value) > 0 then begin
FContentType := Value;
end else begin
if Length(FFileName) > 0 then begin
FContentType := GetMIMETypeFromFile(FFileName);
end else begin;
FContentType := sContentTypeOctetStream;
end;
end;
end;
function TFormDataField.GetFieldValue: string;
begin
result:=FData.DataString;
end;
procedure TFormDataField.SetFieldValue(const Value: string);
begin
FData.Size:=0;
FData.WriteString(Value);
end;
end.
SlymRO (2007-02-09 09:32:00) [2]USAGE:
FormDataFields:=TFormDataFields.Create;
try
ParseRequest(RequestInfo,FormDataFields);
if FormDataFields.Count=0 then
begin
ResponseInfo.ContentText:=Format(HTMLStr,[FormStr]);
exit;
end;
FormDataField:=FormDataFields.ItemByName['Unload'];
FileName:=ExtractFileName(FormDataField.FileName);
CheckName(FileName);
UnloadPath:=ServerHandles.ReadIniString('SendUnload','Path','');
if (Length(UnloadPath)=0) or (not DirectoryExists(UnloadPath)) then
raise Exception.Create('Директория выгрузок не доступна');
UnloadPath:=IncludeTrailingPathDelimiter(UnloadPath);
MaxFilesCount:=StrToIntDef(ServerHandles.ReadIniString('SendUnload','MaxUnloadFi les','0'),0);
if MaxFilesCount>0 then
if CountFiles(UnloadPath)>MaxFilesCount then
raise Exception.Create('Достигнут предел количества файлов в директории выгрузок');
FileStream:=TFileStream.Create(UnloadPath+FileName,fmCreate);
try
FileStream.CopyFrom(FormDataField.Data,0);
finally
FileStream.Free;
end;
finally
FormDataFields.Free;
end;
sairus (2007-02-08 16:21:00) [3]Если не затруднит, то пожалуйста... очень буду благодарен... С Делфи думаю не будет проблем-переведу...
proxymus@ukr.net
Спасибо.
SlymRO (2007-02-08 07:18:00) [4]1. Для передачи файлов (особенно "через веб-браузер") должен использоваться <FORM method=post enctype="multipart/form-data"
2. Стандартных средств для обработки multipart в IdHTTPServer нет
Варианты:
1. Придумывать обработку multipart самому
2. Попросить у меня... но у меня на Delphi :)