IPB

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в эту темуОткрыть новую тему
> Отправка файла!
denizk
сообщение 6.1.2011, 15:18
Сообщение #1


Пользователь


Группа: Активисты
Сообщений: 654
Регистрация: 31.10.2007
Пользователь №: 18 005



Задача:
Отправить файл с сервера на клиент.

Реализация:
Реализация почерпнута из интернета.
Для отделения команд от файла использована следующая схема "file#file.txt#16",команда + разделитель + имя файла + разделитель + размер файла.

Код сервера:
Добавляю буфер куда будет писаться файл.
Код

var   Form1: TForm1;  
MS: TMemoryStream; // Буфер для файла


Открываем сокет при старте приложения.
Код

procedure TForm1.FormCreate(Sender: TObject);
begin
  ServerSocket1.Open; // Открываем сокет
end;


Закрываем сокет при закрытии приложения.
Код

procedure TForm1.FormDestroy(Sender: TObject);
begin
ServerSocket1.Close; // Закрываем сокет
end;


Посылаем файл при нажатии на кнопку.
Код

procedure TForm1.Button1Click(Sender: TObject); // Передаём файл
var
Size: integer;
P: ^Byte;
begin
MS := TMemoryStream.Create; // Создаём буфер для файла
MS.LoadFromFile(Edit1.Text); // Загружаем файл в буфер
// Посылаем информацию о файл (команда # название # размер)
ServerSocket1.Socket.Connections[0].SendText('file#'+Edit1.Text+'#'+IntToStr(MS.Size)+'#');
MS.Position := 0; // Переводим каретку в начало файла
P := MS.Memory; // Загружаем в переменную "P" файл
Size := ServerSocket1.Socket.Connections[0].SendBuf(P^, MS.Size); // Посылаем файл
// Выводим прогресс
ProgressBar1.Position := Size*100 div MS.Size;
StatusBar1.SimpleText := 'Отправлено '+IntToStr(Size)+' из '+IntToStr(MS.Size)+' байт'
end;


В событие OnClientRead компонента TServerSocket пишу следующее:
Код

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
if Socket.ReceiveText = 'end' then // Если клиент принял файл, то...
begin
StatusBar1.SimpleText := 'Клиент принял файл';
MS.Free; // Убиваем буфер
end;
end;


На сервере использовал следующие компоненты: TServerSocket, TButton, TEdit, TProgressBar и TStatiusBar. В TEdit пишу имя пересылаемого файла,прогресс бар для получения инфы об отправке,статусбар показывает размер пересылаемого файла и сведения о установке конекта,серверсокет собственно для передачи.
Порты одинаковые на клиенте и сервере использую 2545 или тому подобные.

Код клиента:
Записываем переменные в Private и объявляем процедуру
Код

procedure Writing(Text: string); // Процедура записи в данных в буфер
private
{ Private declarations }
Name: string; // Имя файла
Size: integer; // Размер файла
Receive: boolean; // Режим клиента
MS: TMemoryStream; // Буфер для файла


При создании сервера открываем сокет и ждём передачи файла.
Код

procedure TForm1.FormCreate(Sender: TObject);
begin
ClientSocket1.Open; // Открываем сокет
Receive := false; // Режим клиента - приём команд
end;


При завершении приложения закрываем сокет.
Код

procedure TForm1.FormDestroy(Sender: TObject);
begin
ClientSocket1.Close; // Закрываем сокет
end;


Процедура Writing.
Код

procedure TForm1.Writing(Text: string);
begin
if MS.Size < Size then // Если принято байт меньше размера файла, то...
MS.Write(Text[1], Length(Text)); // Записываем в буфер
// Выводим прогресс закачки файла
ProgressBar1.Position := MS.Size*100 div Size;
StatusBar1.SimpleText := 'Принято '+IntToStr(MS.Size)+' из '+IntToStr(Size);
if MS.Size = Size then // Если файл принят, то...
begin
Receive := false; // Переводим клиента в нормальный режим
MS.Position := 0; // Переводим каретку в начало буфера
MS.SaveToFile(Name); // Сохраняем файл
ClientSocket1.Socket.SendText('end'); // Посылаем команду "end", то есть файл принят
MS.Free; // Убиваем буфер
StatusBar1.SimpleText := 'Файл принят';
end;
end;


В событие OnClientRead компонента TClientSocket вписываю:
Код

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
Rtext: string; // Принятый текст
begin
Rtext := Socket.ReceiveText;
if Receive then // Если клиент в режиме приёма файла, то...
Writing(RText) // Записываем данные в буфер
else // Если клиент не в режиме приёма файла, то...
if Copy(Rtext, 0, Pos('#', Rtext) -1) = 'file' then // Если это файл, то...
begin MS := TMemoryStream.Create; // Создаём буфер для файла
Delete(Rtext, 1, Pos('#', Rtext)); // Определяем имя файла
Name := Copy(Rtext, 0, Pos('#', Rtext) -1); // Определяем имя файла
Delete(Rtext, 1, Pos('#', Rtext)); // Определяем размер файла
Size := StrToInt(Copy(Rtext, 0, Pos('#', Rtext) -1)); // Определяем размер файла
Delete(Rtext, 1, Pos('#', Rtext)); // Удаляем последний разделитель
Label1.Caption := 'Размер файла: '+IntToStr(Size)+' байт'; // Выводим размер файла
Label2.Caption := 'Имя файла: '+Name; // Выводим имя файла
Receive := true; // Переводим сервер в режим приёма файла
Writing(RText); // Записываем данные в буфер
end;
end;


Соединение есть,файл посылается вроде,но не известно куда,т.к. не приходит! Проблема походу с кодировкой,подправьте кто-нить как правильно!
Пользователь в офлайнеКарточка пользователяОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Tanker
сообщение 11.1.2011, 19:33
Сообщение #2


Пользователь


Группа: Активисты
Сообщений: 363
Регистрация: 26.11.2009
Пользователь №: 22 377



вот еще пример пересылки файла http://delphi-faq.zoxt.net/100.htm
и вот http://delphi-faq.zoxt.net/c16.htm

по-моему сначала надо проверить, что команда file# дошла... или вообще что-нибудь
выведи там при приеме сообщение какая команда пришла


--------------------
Успехов!
Пользователь в офлайнеКарточка пользователяОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
denizk
сообщение 12.1.2011, 14:24
Сообщение #3


Пользователь


Группа: Активисты
Сообщений: 654
Регистрация: 31.10.2007
Пользователь №: 18 005



Цитата(Tanker @ 11.1.2011, 19:33) *

вот еще пример пересылки файла http://delphi-faq.zoxt.net/100.htm
и вот http://delphi-faq.zoxt.net/c16.htm

по-моему сначала надо проверить, что команда file# дошла... или вообще что-нибудь
выведи там при приеме сообщение какая команда пришла

Ага,спасибо)) гляну:сегодня надо одну прогу дописать и другую написать ещё успеть,до завтра! biggrin.gif
Пользователь в офлайнеКарточка пользователяОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
denizk
сообщение 19.1.2011, 21:50
Сообщение #4


Пользователь


Группа: Активисты
Сообщений: 654
Регистрация: 31.10.2007
Пользователь №: 18 005



В общем перекомпил проект в дельфи 7 и всё нормально!

А в 2009-2010 дельфи решается проблема так SendText(S) на SendBuf(Pointer(S)^, Length(S)*Sizeof(Char)*2); надо менять и всё почти,единственный косяк,что файл приходит больше чем был!
Пользователь в офлайнеКарточка пользователяОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Tanker
сообщение 20.1.2011, 19:13
Сообщение #5


Пользователь


Группа: Активисты
Сообщений: 363
Регистрация: 26.11.2009
Пользователь №: 22 377



может, за счет выоавнивания до кратности 64 или 32? или сильно длиннее?


--------------------
Успехов!
Пользователь в офлайнеКарточка пользователяОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения

Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия Сейчас: 20.5.2012, 23:56