|
[ Nemanja Avramović @ 21.03.2005. 18:14 ] @
| E ljudi, napravio sam neku funkciju koja od onog stringa koji ftp server vrati pri listingu vraca sve redom :) I to sve radi, ali me zanima petlja koja ce proci kroz sve direktorijume (koristeci moj record da vidi da li je item fajl ili dir). Znaci treba mi nesto kao u DOS-u komanda: dir *.* /s, tj. recursive... ali na serveru!
Evo mog .pas fajla:
Code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Psock, NMFtp;
//define ftp item type
type
TFTPItem = record
Name,User,Group,Permissions,Date:string;
Size,Number:integer;
IsFile:boolean;
end;
type
TForm1 = class(TForm)
NMFTP1: TNMFTP;
procedure NMFTP1ListItem(Listing: String);
procedure FormCreate(Sender: TObject);
procedure NMFTP1Connect(Sender: TObject);
private
function ParseFTPItem(pFTPItem: string): TFTPItem;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.ParseFTPItem(pFTPItem:string):TFTPItem;
var tmp,zFTPItem,date:string;
i,o:integer;
begin
zFTPItem:=pFTPItem;
//parse given string
zFTPItem:=Trim(zFTPItem); //remove blanks
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
Result.Permissions:=trim(tmp); //whole tmp is permissions, but first char tells us whether this is file or not
if tmp[1]='d' then Result.IsFile:=False //find out whether item is file or not
else Result.IsFile:=True;
//let's extract stupid number :)
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
Result.number:=StrToInt(tmp[1]); //we got number!!!
//now user is our target
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
Result.User:=trim(tmp); //this should be user
//group is next
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
Result.Group:=trim(tmp); //this should be group
//let's now get file size
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
Result.Size:=strtoint(trim(tmp)); //this should be size
//date...
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
date:=Trim(tmp);
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
date:=date+'-'+Trim(tmp);
i:=POS(' ',zFTPItem); //find space (end of word)
tmp:=copy(zFTPItem,0,i); //copy till space (1st word)
zFTPItem:=StringReplace(zFTPItem,tmp,'',[]); //remove word from FTPItem
zFTPItem:=Trim(zFTPItem); //remove blanks
date:=date+'-'+Trim(tmp);
Result.Date:=trim(date); //this should be date
//finally, get item's name
Result.Name:=trim(zFTPItem); //this should be name
end;
procedure TForm1.NMFTP1ListItem(Listing: String);
var item:tftpitem;
begin
item:=ParseFTPItem(Listing);
ShowMessage('Name: '+item.Name);
ShowMessage('Size: '+IntToStr(item.Size));
ShowMessage('Is File? '+BoolToStr(item.IsFile,true));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
NMFTP1.Host:='localhost';
NMFTP1.UserID:='avram';
NMFTP1.Password:='moj_pass';
NMFTP1.Connect;
end;
procedure TForm1.NMFTP1Connect(Sender: TObject);
begin
NMFTP1.ChangeDir('www');
NMFTP1.List;
end;
end.
|
[ bancika @ 21.03.2005. 19:21 ] @
kad zatrazis FileList od servera on vraca i fajlove i direktorijume, napravi rekurzivnu funkciju koja ce da pokupi listu sa servera, rekurzivno pozove sebe za direktorijume a fajlove izlista(ili kopira ili sta vec). kad obilazis sve pod-foldere u toj funkciji izmedju svaka dva moras da vratis direktorijum za jedan unazad (tipa cd..) da bih mogo da otvoris sledeci folder u ovom koji se skenira trenutno
evo pseudokoda otprilike
Code:
function list(folder: string);
begin
get(files)
for i:=0 to files.count-1 do
if jesteFolder(files[i]) then
begin
list(folder+files[i]);
chdir('..');
end
else
write(files[i])
end;
[ miniC @ 21.03.2005. 20:24 ] @
Pa ako ces da download-ujes ceo sajt, mozes da koristis WEBZIP ili neki drugi slicni program.
[ Nemanja Avramović @ 21.03.2005. 22:41 ] @
Citat: bancika: kad zatrazis FileList od servera on vraca i fajlove i direktorijume, napravi rekurzivnu funkciju koja ce da pokupi listu sa servera, rekurzivno pozove sebe za direktorijume a fajlove izlista(ili kopira ili sta vec). kad obilazis sve pod-foldere u toj funkciji izmedju svaka dva moras da vratis direktorijum za jedan unazad (tipa cd..) da bih mogo da otvoris sledeci folder u ovom koji se skenira trenutno
evo pseudokoda otprilike
eh, to sam znao, medjutim tu ima problem.. kada uradim deo if FOLDER, i pozovem List ponovo, server mi javi: Error 500(mislim da je 500) - command in progress... zato sto listing vec radi... dakle, to nije greska delphija, vec mi FTP vraca to..........
sto ce reci da moram da pravim neki queue, a to malo... teze... zar ne?
@miniC ... iz Delphi aplikacije koju sam ja pravio zelim da downloadujem sve :)
[ Srki_82 @ 21.03.2005. 23:00 ] @
Sta mislis o ovoj ideji. Prvo pokupis podatke o root folderu na FTP-u. Tu ces dobiti sve foldere i fajlove. Te podatke stavi u StringList ili neki prikladniji tip podataka (array, neki collection ili nesto slicno). Nastavicu dalje s pretpostavkom da koristis StringList. Svaki item u string listi ima i rezervisano mesto za neki objekat i u njemu mozes da cuvas dodatne informacije. Kada naidjes na fajl tu mozes upisati velicinu, atribute, vreme kreiranja i ko zna sta jos. Kad naidjes na folder jednostavno za objekat stavi samo nil. I tako dok ne zavrsis root. Time bi imao u StringList-i sve fajlove (oni itemi koji za objekat nemaju nil (ili kako vec odlucis da ih prepoznajes)) i foldere (oni sa nil objektom ili nekom drugom oznakom). Sada krenes redom da trazis kroz StringList koji su kreirao i pronadjes prvi folder i za njegov objekat postavis novu StringList-u u koju ces ponovo da punis na isti nacin. I tako za sledeci folder... itd. Imaces prilicno lepu strukturu. Sve ti je u memoriji, StrinList moze lepo da se sortira za potrebe prikazivanja... mislim da bi to moglo tako da se uradi. Nadam se da ti je ovo malo pomoglo.
[ Nemanja Avramović @ 22.03.2005. 00:08 ] @
jeste pomoglo, ali malo :)
moze li parchence koda? plizzzzzzzz
[ Srki_82 @ 22.03.2005. 10:20 ] @
Ovo je samo pseudo kod... nadam se da ce ti pomoci
Code:
type
FTPItemData = class
Naziv: String;
Velicina: Cardinal;
Datum: TDateTime;
Fajl: Boolean; // Ako je True to je fajl, u suprotnom je
// folder
SubItems: TStringList; // Ovde drzimo podatke o fajlovima
// ako je trenutni Item folder
// Sve sto ti je jos potrebno
end;
function GetFTPItemInfo(FTPItem: String): FTPItemData;
begin
Result := FTPItemData.Create;
// Ovde pokupis naziva, velicinu i sve sto ti treba
// kao sto si i do sad radio u svojoj proceduri i
// dodas na kraju
Result.SubItems := nil;
end;
function GetFTPData(Folder: String): TStringList;
var
S: TStringList;
ItemData: FTPItemData;
I: Integer;
begin
S := TStringList.Create;
// Ne znam tacno kako uzimas podatke sa FTP-a
// pa cu pisati nesto uopsteno samo da vidis kako bi
// to trebalo da radi
GetFirstFTPItem(Folder, ItemData);
// Recimo da funkcija GetFirstFTPItem uzima putanju do foldera
// koji zelis da pogledas i vraca ti prvi Item. Nesto kao
// FindFirst kad trazis fajlove na svom racunaru.
Repeat
S.AddObject(ItemData.Naziv, ItemData);
Until not GetNextFTPItem(Folder, ItemData);
// Recimo da funkcija GetNextFTPItem uzima putanju do foldera
// koji zelis da pogledas i vraca ti sledeci Item. Nesto kao
// FindNext kad trazis fajlove na svom racunaru.
// Ovo ce napuniti string list podacima iz jednog foldera
// sad jos samo da pokupimo podatke iz podfoldera
for I := 0 to S.Count - 1 do
begin
ItemData := FTPItemData(S.Objects[I]);
if not ItemData.Fajl then
begin
ItemData.SubItems :=
GetFTPData(Folder + '/' + ItemData.Naziv);
end;
end;
end;
Vrlo je bitno da posle uradis ItemData.Free i StringList.Free za sve Iteme i liste koje si kreirao ili ce memorija da ti curi na sve strane.
[ Nemanja Avramović @ 23.03.2005. 00:33 ] @
hvala ti najlepse!!!
pogledacu ovo l8r, sad sam bas bas zauzet, ali hvala hvala hvala
[ Nemanja Avramović @ 25.03.2005. 20:05 ] @
ja ovo nisam uspeo :((((
a pazi... ti opet ovde zoves rekurzivno (u funkciji GetFTPData imas pozivanje iste)...
mora queue pa to ti je :(
[ Srki_82 @ 25.03.2005. 20:55 ] @
Znam da ima, ali zato imas ono GetNextFTPItem. Ta funkcija bi trebala kada nema vise Itema da vrati da zatvori konekciju sa FTP serverom, a GetFirstFTPItem da je otvori. Nisam bas siguran kako to ide sa FTP serverima. Mozda u toj komponenti koju koristis za FTP posle citanja liste fajlova moras da pozoves neku funkcijicu da zavrsi komadnu koja izaziva Error 500 - command in progress.
Ako ti nije frka posalji kod na forum ili meni na mail pa cu probati da ti otkucam taj deo za listanje.
[ Nemanja Avramović @ 25.03.2005. 23:31 ] @
koda nema :( jer sam sve obrisao (mada i nije bilo mnogo)... a sacuvao sam moj type i funkciju za odredjivanje svojstava ftpitem-a (ono sto stoji gore u mom prvom postu)...
problem je sto ja mogu jedino da pozovem NMFTP1.List da listam trenutni folder (koji pozivam sa NMFTP1.ChangeDir('ftp/putanja/do/foldera'); a onda se za svaki item (fajl/folder) poziva event NMFTP komponente (za svaki red ispisa se pozove NMFTP1.OnListItem)... drugacije ne mogu listati item-e (valjda).
ako bolje pogledas gornji primer (prvi post), videces...
[ Srki_82 @ 26.03.2005. 01:04 ] @
Onda ovako:
1. Pozoves FTP.List (root)
2. Pozove se event za Item
3. Uzmes podatke i ubacis ih u StringList kao sto sam ti rekao
4. Goto 2. dok ima itema
5. Kad se zavrsi sa root-om pregledas StringList i kad naidjes na folder krenes iz pocetka (Goto 1.) samo umesto Root stavis folder na koji si naisao.
To bi moglo da radi i sa onim primerom koji sam ti dao.
Kad pozoves GetFirstItem ta funkcija u pozadini odradi FTP.List i sacuva sve sto dobije iz eventa FTP kontrole u StringList i vrati prvu vrednost. GetNextItem bi vracala sledecu, sledecu, sve dok ne bi dosla do kraja. Tako bi onaj kod koji sam ti dao radio.
Kod tebe je greska sto verovatno u tom eventu koji ti daje FTP komponenta za svaki item ti ako naidjes na folder odmah pokusavas da uzmes sta se nalazi u njemu, a FTP komanda za izlistavanje jos nije gotova. Zato ti se i javlja ona greska.
[ Nemanja Avramović @ 26.03.2005. 01:25 ] @
da, upravo sam to radio i to mi je bila greska
ali ne kapiram te opet (sitni satiiiii)
kako da vidim kad je zavrsio sa rootom?
zar mi ne treba za svaki folder stringlist? ili... aaaaaaaaaaaa, poludecu :D
[ Milos D @ 26.03.2005. 12:23 ] @
Ako hoces ozbiljnije da koristis FTP, onda bolje da upotrebis INDY ili ICS komponente za FTP jer NMFTP je bagovit. Ali, komponente nisu bitne za tvoj trenutni problem, moras da stavljas svaki poddirektorijum koji zelis da obradis u TStringList, i kada LIST komanda zavrsi (valjda ima event za to), "izvadis" prvi poddirektorijum iz liste i izlistas njega, i tako sve dok se lista ne isprazni. Mislim da ti je dovoljan jedan TStringList.
[ Srki_82 @ 26.03.2005. 12:34 ] @
Da te ne zamaram ponovo mojim objasnjenima... izvoli primer pa probaj sam da shvatis o cemu se radi.
Uradio sam sve sa TreeView-om pa ces lepo moci da vidis sta se nalazi u kom folderu. Fajlovi na kraju imena imaju (file), a folderi (dir). Ne koristim Binary nego obican ASCII prenos jer za imena i ne treba Binary. Takodje koristim anonymus logovanje pa ako neki server bude zahtevao pravo logovanje moraces malo da promenis kod. U edit-u ukucas ime servera i kliknes na Start... onda ce da radi nekoliko minuta u zavisnosti od velicine sajta. Ako te mrzi da cekas uvek mozes da kliknes na Stop i za par trenutaka ce sve stati i imaces delimicnu listu. To je to... pogledaj i reci da li si tako nesto hteo?
[ Nemanja Avramović @ 26.03.2005. 17:45 ] @
Missing:
properties:
IdFTP1.MaxLineAction
IdFTP1.ReadTimeout
IdFTP1.Username
IdFTP1.ProxyType
IdFTP1.Port
file:
IdFTPList.dcu
verovatno si radio sa novijom verzijom delphija (novijom od D6) :((
[ Srki_82 @ 26.03.2005. 17:57 ] @
Delphi 7. Ta svojstva i nisu tako bitna. Pogledaj kod i videces kako sam sve uradio.
P.S.
Mogu da ti iskompajliram kod pa da vidis kako radi.
[ Nemanja Avramović @ 26.03.2005. 18:00 ] @
pa ono... iskompajliraj.. a ja cu pogledati...
[ Srki_82 @ 27.03.2005. 00:04 ] @
Da bi mogao ovo da iskompajliras trebaju ti nove Indy kontrole. Mozes besplatno da ih skines sa www.nevrona.com/indy
Skini exe ovde: http://www.geocities.com/srki_82/Project1.zip
P.S.
Obrisacu fajl sa servera za par dana pa mi javi kad ga budes skinuo.
[ Nemanja Avramović @ 27.03.2005. 03:52 ] @
ok, pogledacu ujutru kad se otreznim :)
p.s. downloadovao sam ovo... brisi sa servera
[ Nemanja Avramović @ 27.03.2005. 23:07 ] @
ummmm... pogledaj:

[ Srki_82 @ 27.03.2005. 23:16 ] @
Pa to je ono sto tvoj server vraca :)
Ja sam probao na ftp.microsoft.com, ftp.westwood.com, ftp.gnu.org i ftp.keystealth.org i sve je radilo bez greske. Mozda tvoj server radi malo drugacije od ovih i daje te foldere koji se zovu samo '.'
[ _v!rus_ @ 27.03.2005. 23:56 ] @
A bre jahvrame, jahvrame, zajebavas tu postene pomagace, ko da ne umes da ispravis sam...
Pocevsi od PC-DOS-a 1.0 na ovamo, pored [..] koje referencira Parent direktorijum, postoji i [.] koje referencira TRENUTNI direktorijum. Na slicnu stvar sam naleteo praveci klon WinCMD-a za linux  .
Ne znam srkijev kod, ali sigurno postoji rek. f-ja koja izlistava sadrzaj direktorijuma i ako naleti na direktorijum pri izlistavanju, rekurzivno poziva samu sebe. Dodaj proveru pre rek. poziva:
if (DirName <> '.') and (DirName <> '..') then RekPoziv; //ili nesto slicno
Samo me cudi da posle 8 rek. poziva (sudeci po slici) kod nastavi izlistavanje (trebalo bi da uleti u beskrajnu rekurziju i izazove stack overflow)...
[ Srki_82 @ 28.03.2005. 00:24 ] @
Mozda bi kod uleteo u beskonacnu rekurziju da JaHvram nije kliknuo na Stop 
Uvek u svim rekurzivnim funkcijama stavljam "sigurnosnu" proveru da bih mogao da zaustavim rekurziju pritiskom na dugmence ako nesto krene kako ne treba 
Probaj da sve foldere koji pocinju sa tackom da izostavis iz provere kao sto _v!rus_ kaze. To bi trebalo da pomogne. Nije mi ni palo na pamet da ce se tako nesto pojaviti na ftp serveru i zato to nisam ni predvideo. Moja greska 
[ Nemanja Avramović @ 28.03.2005. 11:16 ] @
ok, pogledacu... a i posle duzeg `listanja` izbaci stack overflow... ajde pogledacu sta mogu da uradim.....
[ Srki_82 @ 28.03.2005. 11:54 ] @
Ako ti nije bitno da bas odmah pri prvom listanju uzmes sve podake o fajlovima sa servera (sto i nije bas najbolje jer ako je neki malo veci ftp sajt, a losa veza ima da ti radi listanje satima, a mozda i danima) uvek mozes da izlistas samo root i gotovo. Kad korisnik pokusa da otvori neki folder ti onda uzmes podatke za taj folder i u TreeView-u dodas nove fajlove i foldere (TreeView ti sluzi kao neka vrsta cashe-a). Tako je mnogo bolje da radis pod uslovom da ti nije bas bitno da odmah imas sve podatke  Tako radi i Explorer u Windows-u.
[ Nemanja Avramović @ 28.03.2005. 22:18 ] @
ma bitno mi je samo da moze da se skine ceo sajt (pa mu ja onda sa if funkcijama odredjujem da li ce da ignorise velike fajlove, koje foldere, koje tipove fajlova...)
btw. sje*'o sam delphi... radi sad... ali jedva... skinem ja novi Indy10 i on mi kaze da obrisem stari Indy... i ja obrisem... i sad mi ne radi tvoja app (sa novim Indy-jem, kaze opet nedostaju neki Property-ji, i ne radi mi par drugih VCL... :((()
Da li neko zna gde skinuti stari Delphi... i ljudi, kako da predjem na noviji delphi kad imam krsh komponenti samo za shesticu... a od toga su mi neke bas bitne...
@Srki (offtopic): evo ti jos dve skin komponente (w/ source, ofcourse) http://avramyu.spymac.net/trash/Srki_82_skins_Delphi.zip
[ Srki_82 @ 28.03.2005. 23:25 ] @
Ako su ti komponente samo za sesticu nema ti spasa. Samo Delphi 6 mozes da koristis. Ako imas source svih potrenih komponenti onda nije problem. Instaliras Delphi 7, otvoris *.dpk fajlove komponenti i gde imas recomi vcl60.bpl ili rtl60.bpl ti ih samo zamenis sa vcl70.bpl i rtl70.bpl i ima da rade i na Delphi 7... uglavnom sve 
Ako su vec kompajlirane mozes samo da se nadas da ce kreatori izbaciti i verziju za Delphi 7.
P.S.
Moj programcic radi sa verzijom Indy-a koja ide sa Delphi 7. Ne radi sa novom 9. ni sa novom 10. verzijom. I ja sam se zeznuo isto kao i ti pa sam danas morao ponovo da instaliram Delphi 
[ Nemanja Avramović @ 28.03.2005. 23:53 ] @
e jbg... onda ovo pitanje stoji on standby do daljnjeg :(((((
a nisi pokusao sa NMFTP?
[ Srki_82 @ 29.03.2005. 00:15 ] @
Nisu bitne komponente nego princip :)
Ovaj primer koji sam ja uradio mozes da uradis i sa tim komponentama. Pogledao sam malo kako NMFTP radi. Kad pozoves list proceduru on ti daje onaj event za svaki file, folder ili sybolic link i kad se svi eventi zavrse zavrsava se i list procedura tako da uvek mozes da znas kad je zavrseno listanje nekog foldera.
Teoriju sam ti vec par puta objasnio... pokusaj samo da prodjes kroz kod i da polako pises svoj. Vrlo je jednostavno. Samo moras da obratis paznju da iz eventa koji se javlja kada se listaju folderi ne smes da listas drugi nego tek kad se list procedura zavrsi.
[ Nemanja Avramović @ 29.03.2005. 11:17 ] @
ajoooooooj :(
KAKO da vidim kad je zavrsilo?! Vec sam pitao ovo... jesi video one komponente?
[ Srki_82 @ 29.03.2005. 15:25 ] @
Neces videti nikako ako samo pitas 
Kad se zavrsi procedure List zavrsilo se listanje
To otprilike ide ovako:
List (pozvao si je)
...Event
...Event
...Event
...Event
...Event
...Event
...Event
...Event
List se zavrsi
Eto... vrlo jednostavno. Dok se svi Eventi za dati folder ne pozovu List procedura se ne zavrsava.
To mozes proveriti ako napises ovakav kod.
Code: Application.MessageBox('Pre listanja','Info');
FTP.List;
Application.MessageBox('Posle listanja','Info');
Event napises ovkao
Code: begin
Application.MessageBox('Event','Info');
end;
I dobices
Pre listanja
Event
Event
Event
.
.
.
Posle listanja
Nadam se da si me ovog puta razumeo.
[ Nemanja Avramović @ 29.03.2005. 20:17 ] @
ajoj... tek kad mi nacrtas :) ja vidim :P ok... znam da necu uspeti (jednostavno kad ne uspem iz prve... druge... trece... onda necu nikad), ali pokusacu
[ Srki_82 @ 30.03.2005. 00:50 ] @
Javi kako ti ide i ovog puta nemoj da brises kod  Kad negde zapne daj kod ovamo da ti pomognemo
(offtopic): Video sam te komponente jos odavno, na osnovu njih i radim svoje komponente. Jedini problem za sada su scroll box u drugim kontrolama (list box, combo box...) i na formama, ali valjda cu i to skontati.
[ Nemanja Avramović @ 30.03.2005. 01:12 ] @
"Da kapetane!" (Sponge Bob SquarePants)
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|