Is it possible to use TIdFTP client in controller enpoint? I have tried to use this code in controller action to upload files directly to ftp server, but there is an error in Put procedure:
...
FTP := TIdFTP.Create(nil);
FTP.Host := FQDN;
FTP.Username:= 'username' ;
FTP.Password:= 'password';
FTP.TransferType := IdFTPCommon.ftBinary;
FTP.Passive := true;
try
EnterCriticalSection(CriticalSection);
FTP.Connect;
FTP.Login;
FTP.ChangeDir('/upload');
FTP.Put(fromFile, toFile, false);
FTP.Quit;
FTP.Disconnect;
finally
FTP.free;
LeaveCriticalSection(CriticalSection);
end;
...
The error is "Cannot assign a TIdFTPClientIdentifier to a TIdFTPClientIdentifier"
The error occured after change of TransferType from ftASCII to ftBinary. (binary files are transfered), although ftASCII is working, but JPG files are corrupted.
Maybe there is a coherence (or conflict) with IOHandler used in DMVCFramework (or IdHTTPWebBrokerBridge) context and IdFTP client self.
Is there any solution how to solve this issue?
Normally out of DMVC context, the code is working.
Thanks.
Related
I have Delphi 7 running on XP SP3.
On my server, I have this directory:
root/public_html/TESTTEST
When I do this:
procedure TForm1.Button3Click(Sender: TObject); // connect
begin
ftp.Host := 'URL';
ftp.port := 21;
ftp.Username := 'xxxxxxx';
ftp.password := 'pppppp';
ftp.Connect;
...
The TIdFTP component connects wonderfully.
And when I expand the code to this:
...
ftp.ChangeDir('/public_html');
ftp.ChangeDir('/public_html/TESTTEST');
ShowMessage(ftp.RetrieveCurrentDir);
...
It shows me:
public_html/TESTTEST
Just for test, I did this:
FTP.makedir('TESTDIR');
And the directory does exist.
public_html/TESTTEST/TESTDIR
Back to public_html/TESTTEST, if I try to use ftp.Put(file1,file2,true); I get this error message:
I won't open connection to 100.126.38.39 (only 77.106.146.15)
Same error when I try ftp.Get(file1,file2,true);
File1 and 2 are adjusted accordingly to I/O, True/False switched - no difference, same error.
When I call ftp.Get(...), the resulting file is created, but it is EMPTY.
To be honest, I don't know what to do. How can I make this work?
In a service running under system account the code below hangs in the TMemIniFile.Create without errors.
If we replace it with TIniFile, it works fine.
It's a Delphi Tokyo 10.2.3 Win32 app running under Windows Server 2012R2. There's no concurrent access to the INI file.
This is the first time (first client) we see this, it has been running fine on many machines.
I have no idea what to look for further. Any ideas?
It 'works' now because we switched to TIniFile, but I'd like to find the cause. From other posts I read here, TINIfile seems to be more finicky than TMemINIfile, my situation is the reverse.
There are no special characters in the INI file and it is created with an ASCII editor.
// This is set in the ServiceCreate:
FIniFileNaam := ChangeFileExt(ParamStr(0),'.INI');
// This is called from the ServiceStart:
procedure TTimetellServiceBase.LeesINI;
var lIniFile : TMemIniFile;
begin
LogMessage(FIniFileNaam, EVENTLOG_INFORMATION_TYPE, cCatInfo, cReadINI); // Logs to event log, we see this
FStartDir := ExtractFilePath(ParamStr(0));
if assigned(FLaunchThreadLijst) then FreeAndNil(FLaunchThreadLijst);
FLaunchThreadLijst := TStringList.Create;
try
if FileExists(FIniFileNaam) then
begin
// Lees waarden uit INI file
lIniFile := TMemIniFile.Create(FIniFileNaam); // This is the call that hangs. The service is unresponsive now.
try
FLaunchThreadLijst.CommaText := lIniFile.ReadString(INISECTIE_SERVICETASKS,'RunIniFiles','');
FMaxTaskDuration := lIniFile.ReadInteger(INISECTIE_SERVICETASKS,'MaxTaskDuration',FMaxTaskDuration);
finally
FreeAndNil(lIniFile);
end;
end;
finally
if (FLaunchThreadLijst.Count = 0) and FileExists(FStartDir + FExeName) then
FLaunchThreadLijst.Add(SDEFAULTTHREADNAME);
LogMessage(Format('FLaunchThreadLijst.CommaText: %s (%d items)',[FLaunchThreadLijst.CommaText,FLaunchThreadLijst.Count]), EVENTLOG_INFORMATION_TYPE, cCatInfo, cLaunchList);
end;
end;
FWIW, INI file contents:
[TASKMANAGER]
RunIniFiles=TTTasks.ini
MaxTaskDuration=2
RestartIniFiles=
KillIniFiles=
I use the internal TZipFile.
When I open the zip then Delphi seems to open it exclusively.
As long as the zipfile isn't freed the file access is denied
lZipFile := tZipFile.Create;
if lZipFile.IsValid( sPath) then begin
lZipFile.Open( sPath, zmRead );
...
// access denied to sPath
end;
lZipFile.Free;
I only want to read. Why delphi is behaving that way?
If I want to access a zip-file several times then I have to make a local copy and work with that copy? I don't really like this workaround. First of all since the zipfile could be huge.
Any idea what I can do to access the same zip in a read-only mode at the same time more than once?
You can create a TFileStream instance opened with the desired share mode. Then use the overloaded Open method of TZipFile that accepts a TStream.
Be aware that TZipFile.IsValid will try to open the file exclusive, too. As IsValid does nothing what Open also does, I added a try-except block to catch any invalid or unaccessible target. The call to IsValid can thus be omitted.
zip := TZipFile.Create;
try
stream := TFileStream.Create(sPath, fmOpenRead + fmShareDenyWrite);
try
try
zip.Open(stream, zmRead);
except
on EZipException do begin
// access denied to sPath
end;
end;
finally
stream.Free;
end;
finally
zip.Free;
end;
I'm having a problem downloading a file using the TidFTP component in Delphi XE2. I am able to get a connection to the FTP site, get a list of files and perform the get command. However, when I try to download a file using the get command the file always downloads larger than the source file. Then the subsequent file is corrupt.
Additionally, if I try to download multiple files, the first file downloads (larger than the source) and the remaining files are skipped. No error is thrown from the get command, it just quits. I tried to hook into some of the events on the TidFTP control like AfterGet and OnStatus but everything appears normal.
I tried using a 3rd party FTP client to access the file and download it just to make sure it was not a problem with our FTP server and that download worked as expected. So I'm thinking it might be related to the TidFTP control or perhaps I'm doing something incorrectly.
Here is the routine I'm using to download the file:
var
ftp: TIdFTP;
strDirectory: string;
begin
ftp := TIdFTP.Create(nil);
try
ftp.Host := 'ftp.myftpserver.com'
ftp.Passive := false;
ftp.Username := 'TestUser';
ftp.Password := 'TestPassword';
ftp.ConnectTimeout := 1000;
ftp.Connect();
ftp.BeginWork(wmRead);
ftp.ChangeDir('/TestArea/');
strDirectory := 'c:\test\';
if not DirectoryExists(strDirectory) then
CreateDir(strDirectory);
ftp.Get('Test.zip', strDirectory + '\' + 'Test.zip', true, false);
ftp.Disconnect();
except
on e: exception do
showMessage(e.message);
end;
end;
You need to set the TIdFTP.TransferType. Its default value is Id_TIdFTP_TransferType, which is ftASCII. You need to use ftBinary instead, and set it before executing the Get:
ftp.Connect();
...
ftp.TransferType := ftBinary;
ftp.Get('Test.zip', strDirectory + '\' + 'Test.zip', true, false);
ftp.Disconnect();
The documentation for TIdFTP.TransferType says in one place that it's automatically set to ftBinary when Login is executed or when Connect is called when AutoLogin is set to true, but you're not executing Login in your code and haven't set AutoLogin. The paragraph immediately following the above statement says:
According to #RemyLebeau in the comments below, the documentation quoted is in error, and TransferType was never set to ftBinary in Login. Leaving the stricken content for future reference.
According to the documentation:
The default value for TransferType is Id_TIdFTP_TransferType, as assigned during initialization of the component.
function UploadToFTP(file: string ; PathSrv : string): Boolean;
var
server, port, user , password: string;
SR : TSearchRec;
begin
Result := True;
FEventLogger := TEventLogger.Create('Upload FTP');
if file <> '' then
begin
try
server := FServer;
port := FPort;
user := FUserName;
password:= FPassword;
FindFirst(file, faArchive, SR);
try // try except
idftp1.Host:= server;
idftp1.Port := StrToInt(port);
idftp1.Username:= user;
idftp1.Password:= password;
idftp1.Connect();
idftp1.Put(file,PathSrv+SR.Name);
except on E: Exception do begin
Result:= False;
FEventLogger.LogMessage('Exception : ' + E.Message , EVENTLOG_ERROR_TYPE , 0, 2);
WriteToLog('Exception: '+ file+' error message: '+ E.Message);
end;
end;
finally
end;
end;
end;
So I have this function that does an ftp upload to some large files on sometimes slow networks. I've tested it localy and it works ok, but on slow networks i get this eror in 99% of the time.
The specified network name is no longer available.
This is a very strange behavior, becouse the FTP is located on a server that has no disconnecting issues. I also try to watch, and it start the file upload and it does almost all the upload before throwing this error. So for example if I have a 100MB file it does 99MB of the upload then throws the error.
Any ideas what is causing this error or what can I do?
Also from time to time I have an other error
Socket Error # 10054
Connection reset by peer.
To mention,i've tried to upload this files using filezilla and it works, so the problem is somewhere in that code, I might miss something.
Are you using Symantec Endpoint Protection or KIS (Kaspersky Internet Security) ? Take a look here, here and here.
The "The specified network name is no longer available." is caused by Symantec Endpoint Protection 11.0, Symantec has identified this as a known issue.
Btw, in your code don't forget to call .Disconnect() after you're finished uploading the file.