powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Synapse FTP Client
24 сообщений из 24, страница 1 из 1
Synapse FTP Client
    #39402459
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте,

Кто работал с FTP в Synapse?

У меня DelphiXE8
Интересует, почему FTPClient.StoreFile - закачка файла с именем '什么国家的企业在自贸区.xls' с локального диска на FTP
делает файл '??????????????.xls', т.е. FTPClient.StoreFile говорит, что все ОК, файл залит, но на FTP чтение директории (FTPClient.List) показывает вопросики.

С другими языками также проблемы, но русский понимает.

Поддерживает ли Synapse FTP юникод UTF8 ?

Заранее благодарен.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39402499
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52Кто работал с FTP в Synapse?Я работал
m52закачка файла с именем '什么国家的企业在自贸区.xls'Но такими извращениями не занимался
m52FTPClient.StoreFile
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
function TFTPSend.StoreFile(const FileName: string; Restore: Boolean): Boolean;
var
  RestoreAt: int64;
begin
  .......
  Result := InternalStor('STOR ' + FileName, RestoreAt);
end;

function TFTPSend.InternalStor(const Command: string; RestoreAt: int64): Boolean;
begin
    ..........
    if (FTPCommand(Command) div 100) <> 1 then
    ..........
end

function TFTPSend.FTPCommand(const Value: string): integer;
begin
    ..........
  FSock.SendString(Value + CRLF);
    ..........
end;

procedure TBlockSocket.SendString(Data: AnsiString);
var
  buf: TMemory;
begin
  {$IFDEF CIL}
  buf := BytesOf(Data);
  {$ELSE}
  buf := Pointer(data);
  {$ENDIF}
  SendBuffer(buf, Length(Data));
end;

И чтобы добить
Код: pascal
1.
2.
3.
4.
5.
6.
{$IFDEF UNICODE}
  {$WARN IMPLICIT_STRING_CAST OFF}
  {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
{$ENDIF}

unit blcksock;

НО! TFTPSend.FTPCommand метод виртуальный. Так, что все в твоих руках
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39449810
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подскажите, можно ли сделать чтобы TBlockSocket.SendString в качестве параметра принимала Data: string, т.е. в UTF8 ?
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39449829
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52Подскажите, можно ли сделать чтобы TBlockSocket.SendString в качестве параметра принимала Data: string, т.е. в UTF8 ?
Можно. Для разовых потребностей можно использовать ансейф-кастинг socket.SendString(AnsiString(Pointer(MyUtf8String))); Но более правильный вариант - написать хелпер для TBlockSocket.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39449851
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я попробовал сделать замену строки
Код: pascal
1.
FSock.SendString(Value + CRLF);

на
Код: pascal
1.
FSock.SendString(AnsiString(Pointer(Value + CRLF)));


получилось вот что:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
function TFTPSend.FTPCommand(const Value: string): integer;
begin
  FSock.Purge;
  //FSock.SendString(Value + CRLF);
  FSock.SendString(AnsiString(Pointer(Value + CRLF)));
  DoStatus(False, Value);
  Result := ReadResult;
end;


Но не работает даже соединение с сервером - отвал по таймауту,

<- 220 (vsFTPd 2.2.2)
-> USER admin
<- 421 Timeout.

авторНо более правильный вариант - написать хелпер для TBlockSocket.
Что такое хелпер? Можно подробнее?
Как все-таки сделать, чтобы TBlockSocket.SendString в качестве параметра принимала Data: string, т.е. в UTF8, а не AnsiString ?

Странно, что в FTPCommand(const Value: string) входной параметр в UTF8 (у меня DelphiXE8), а в FSock.SendString передается AnsiString.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39449859
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробуйте отправить команду FTPCommand('OPTS UTF8 ON'), сервер должен ответить 200 UTF8 mode enabled
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39449860
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52Но не работает даже соединение с сервером
Что не удивительно... У тебя XE8, где дефолтные строки (string) являются строками в кодировке UTF-16, а вовсе не в UTF-8, т.е. каждый символ в строке занимает минимум 2 байта. В этом случае опасный кастинг нужно делать через безопасный кастинг: FSock.SendString(AnsiString(Pointer( Utf8String( Value ) + CRLF)));

m52 Что такое хелпер? Можно подробнее?
Компилябельность не проверял.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
Type

 TBlockSockClassHelper = Class Helper For TBlockSocket

  Public

   Procedure SendString(Const AString : Utf8String); Overload;

 End;

//
Procedure TBlockSockClassHelper.SendString(Const AString : Utf8String);
Begin

 SendBuffer(Pointer(AString), Length(AString));

End;
//


Но сперва, всё же, разберись со строками и их кодировками.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39450086
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я попробовал function TFTPSend.FTPCommand оставить как есть, ничего не меняя, а procedure SendString сделать такой:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
procedure TBlockSocket.SendString(Data: UTF8String);
var
  buf: TMemory;
begin
  {$IFDEF CIL}
  buf := BytesOf(Data);
  {$ELSE}
  buf := Pointer(data);
  {$ENDIF}
  SendBuffer(buf, Length(Data));
end;

, т.е. входной параметр просто заменил с AnsiString на UTF8String
Теперь попробовал скачать с FTP-сервера файл с китайским именем "文件測試.ddp" и он скачался!

Код: pascal
1.
2.
3.
-> RETR /&#25991;&#20214;&#28204;&#35430;.ddp
<- 150 Opening data channel for file download from server of "/文件測試.ddp"
<- 226 Successfully transferred "/文件測試.ddp"


Не совсем понял тогда, зачем мне предложили написать класс TBlockSockClassHelper ?
Может я позже наткнусь на грабли?
Поясните, пожалуйста, кто в теме.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39450087
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52 зачем мне предложили написать класс TBlockSockClassHelper
Для того, чтобы не править исходники синапса.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39450089
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyДля того, чтобы не править исходники синапса.
Но это, конечно, не поможет для разруливания проблем с FTP, т.к. метод хелпера сможет вызывать только твой код, но не код синапса.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39450829
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexeyметод хелпераЯ в самом первом сообщении сказал
_Vasilisk_TFTPSend.FTPCommand метод виртуальный. Так, что все в твоих руках
Что мешает создать наследника TFTPSend и переопределить в нем метод FTPCommand как-то так
_Vasilisk_
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function TMyFTPSend.FTPCommand(const Value: string): integer;
var
  LVal: UTF8String;
begin
    ..........
  LVal := UTF8String(Value + CRLF);
  FSock.SendBuffer(LVal, Length(LVal));
    ..........
end;
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39450835
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Что мешает создать наследника TFTPSend и переопределить в нем метод FTPCommand
Хороший вопрос топикстартеру.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39451000
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ничего особо не мешает.
С этим я попробую.

Сейчас меня интересует другой вопрос - это вопрос докачки файла при копировании с локального диска на FTP.
Если файл начинает копироваться с самого начала, то проблем нет.
Я попробовал в процессе копирования отключить соединение в Windows. Понятно, что копирование файла прервалось. Если обратно включить соединение, перезапустить программу, переконнектиться к FTP и попробовать докачать файл, то программа зависает (по логу, см. ниже видно, что зависает после команды STOR public_html/_exchange/asd.mp4).

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
    // назначаем обработчик событие для сокета
    FTPClient.DSock.OnStatus:=DSockStatus;

    FTPClient.DirectFile:=true;
    FTPClient.DirectFileName:='c:\temp\asd.mp4';
    FTPClient.StoreFile('/public_html/_exchange/asd.mp4', true);

    // убираем обработчик
    FTPClient.DSock.OnStatus:=nil;


Лог FTP:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
-> SIZE public_html/_exchange/asd.mp4
<- 213 7602176
-> PASV
<- 227 Entering Passive Mode (194,58,102,84,174,119).
-> TYPE I
<- 200 Switching to Binary mode.
-> ALLO 20140741
<- 202 ALLO command ignored.
-> REST 7602176
<- 350 Restart position accepted (7602176).
-> STOR public_html/_exchange/asd.mp4
Здесь виснет в function TFTPSend.FTPCommand в Result := ReadResult; - а именно на команде FSock.RecvString(FTimeout);
Почему-то обработчик сокета данных FTPClient.DSock.OnStatus не вызывается.
Программа "висит долгое время, потом может отвалиться по Timeout".


Если удалить файл на FTP и начать качать заново - проблем нет.
Также при скачивании с FTP на локальный диск - проблем нет (докачивается нормально).

Отчего происходит зависание и как его победить?
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39451004
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А еще замечено, что зависания при докачке нет, если выждать минут 5 после восстановления соединения. Такое ощущение, что соединение хоть и появилось, но как-то не до конца. Но ждать несколько минут никому не хочется, ведь Интернет уже есть.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39451019
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52зависания при докачке нет, если выждать минут 5 после восстановления соединения.Вы начинаете заливать файл. На сервере, в потоке подключенного клиента открывается файл на запись и блокируется от модификации другими потоками. Далее - происходит разрыв соединения, но сервер об этом ничего не знает и продолжает держать файл открытым и заблокированным. Вы цепляетесь новым потоком и обращаетесь к заблокированному файлу. Сервер не возвращает ошибки, а ставит запрос в очередь ожидания. По прошествии пяти минут, сервер видит, что в брошенном потоке нет никакой активности, принудительно закрывает соединение и разблокирует файл
m52ждать несколько минут никому не хочется,Тогда уменьшите таймаут на сервере. Мы для своих FTP серверов ставим таймаут в 10 секунд
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39451094
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_ ,

То что вы описали, похоже что так и есть.
Но если при передачи данных по FTP соединение с Интернетом не разрывать, а просто убить программу в диспетчере задач, то после этого докачка работает на УРА, т.е. ничего не блокируется на стороне сервера. Почему так?

Проблема в том, что для моей программы FTP-серверов может быть много (много разных клиентов) и уговаривать каждого клиента настроить свой FTP-сервер, уменьшив таймаут, я не могу.

Есть ли возможность решить вопрос с докачкой, не перенастраивая сервер?
Если нет, то тогда проще будет в случае разрыва связи перезакачать файл заново, чем докачивать.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39451399
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52Почему так?Потому, что серверу приходит какой нибудь "Connection reset by peer" и сервер закрывает соединение сразу же
m52уговаривать каждого клиента настроить свой FTP-сервер, уменьшив таймаут, я не могу.Значит смиритесь. Тем более, что малые таймауты актуальны только для программного доступа. А если сервером пользуются люди через какие-нибудь клиенты, то 5 минутный таймаут самое оно.
m52Есть ли возможность решить вопрос с докачкой, не перенастраивая сервер?Закачивать во временные файлы а потом переименовывать. И периодически подчищать недокачанные файлы
m52то тогда проще будет в случае разрыва связи перезакачать файл заново, чем докачивать.Если хватит прав и удаленный файл открыт сервером с правами FILE_SHARE_DELETE
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39451799
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо за ответы.

Описанное выше "зависание" при докачке наблюдается только у 1 из 6 серверов и только при закачке на FTP (upload).
Можно "забить" или сделать чтобы юзер сам в настройках мог выбирать, что делать:

В случае разрыва связи и восстановления:
(*) Докачивать файл
( ) Закачать файл заново
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39451835
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, когда писал своего клиента, нарвался на такой баг FTP сервера. При запросе размера недозакачанного файла, файл блокировался на запись и эту блокировку нужно было принудительно снимать. Обошел багу таким кодом
Код: pascal
1.
2.
3.
4.
5.
6.
7.
function TMyFTPSend.FileSize(const AFileName: string): Int64;
begin
  Result := inherited FileSize(AFileName);
  // Bug fix for freeFTPd
  if Result <> -1 then
    FTPCommand('SIZE');
end;


Ну и вот моя процедура докачки
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
function TMyFTPSend.StoreStream(const AFileName: string; AStream: TStream;
  ARestore: Boolean): Boolean;
var
  LDataStrm: TStream;
  LRemoteSize: Integer;
begin
  LDataStrm := FDataStream;
  FDataStream := AStream;
  try
    DirectFile := False;
    if ARestore and not FCanResume then begin
      LRemoteSize := Self.FileSize(AFileName);
      if LRemoteSize > 0 then
        Result := InternalStor('APPE '+ AFileName, LRemoteSize)
      else
        Result := StoreFile(AFileName, False);
    end else
      Result := StoreFile(AFileName, ARestore);
    // freeFTP bug fix
    if Result then begin
      LRemoteSize := Self.FileSize(AFileName);
      if LRemoteSize < AStream.Position then begin
        AStream.Position := LRemoteSize;
        FResultString := 'Invalid remote file size';
        Result := False;
      end;
    end;
  finally
    FDataStream := LDataStrm;
  end;
end;
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39452108
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_ ,

Я смотрю, у вас TMyFTPSend.StoreStream - это процедура докачки из потока Stream в файл на сервере путем присоединения APPE.
Мне нужно докачать не из потока, а из файла:
Код: pascal
1.
2.
    FTPClient.DirectFile:=true;
    FTPClient.DirectFileName:=OpenDialog1.FileName;

Я пробовал в TFTPSend.StoreFile встроить такой механизм:
Код: pascal
1.
2.
3.
RestoreAt := Self.FileSize(FileName);
if RestoreAt<>-1 then FTPCommand('SIZE'); // костыль, который не помог
InternalStor('APPE '+ AFileName, RestoreAt);

, но также зависает на InternalStor, видимо костыль в виде FTPCommand('SIZE'); не помог в моем случае, либо я что-то не так делаю.
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39452152
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52сервере путем присоединения APPE.Причем вначале проверяется, а имеет ли смысл вызывать такую команду
_Vasilisk_
Код: pascal
1.
if ARestore and not FCanResume then begin

m52
Код: pascal
1.
 // костыль, который не помог

Вот я же не зря это сделал в переопределенной виртуальной функции
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39457105
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А что за ошибка "553 Could not create file" возникает при попытке отправить файл с локального диска на FTP ?

Эта ошибка то возникает, то нет. Иногда все файлы копируются нормально, а иногда на некоторых выдает эту ошибку.
Файлы не используются другими приложениями.
Отключение Касперского не помогает (видимо, не в этом дело).
Переконнект к FTP тоже не помогает.

В случае этой ошибки повторная закачка файла не проходит - опять получаем эту же ошибку.

НО! Если в случае ошибки выждать секунд 40 и повторить операцию, то почти всегда новая закачка файла успешна.

Как избежать этой ошибки или ожидания в 40 сек перед второй попыткой?
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39457179
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52А что за ошибка "553 Could not create file"Невозможно создать файл
m52Файлы не используются другими приложениями.Откуда такая уверенность?
m52Переконнект к FTP тоже не помогает.А перезапуск FTP демона?
m52Как избежать этой ошибкиПосмотреть логи сервера
...
Рейтинг: 0 / 0
Synapse FTP Client
    #39457271
m52
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощения, похоже, я сам виноват, что пытаюсь скопировать файл в несуществующую папку. Отсюда и ошибка.
Жаль что нет возможности одной командой типа ForceDirectories создать сразу полный путь вида "/www/site/_exchange/folder1", а затем скопировать туда файл.
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Synapse FTP Client
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]