类似FTP服务器的程序,如何处理文件共享冲突 ( 积分: 200 )

  • 主题发起人 主题发起人 tdp
  • 开始时间 开始时间
T

tdp

Unregistered / Unconfirmed
GUEST, unregistred user!
做一个在网络上同步文件的程序
客户端定时从服务端检查文件是不是更新,如果更新就下载文件。
下载的时候服务端使用下面的方法打开文件开始传送。
TFileStream.Create(FileName, fmOpenRead);

我现在想到有下面的几种情况需要处理,有谁做过类似的程序,指点一下

多个客户端同时下载一个文件;
客户端正在下载文件的时候,服务端要更新文件;
服务端正在更新文件的时候,客户端开始下载;
 
没做过,关注中.....

P/V操作?
 
我现在的做法是,忽略客户端的访问
更新文件时如果有FileStream打开的话直接释放,然后更新文件


现在论坛的速度怎么这么慢,打开一个页面要好长时间
 
你可以维护一个TFileStream的列表,保存正在下载的对象和文件名,在需要更新的时候可以查到这个对象,如果更新的账户是高用户级的,可以直接给每个下载的客户端发Abort命令终止,然后执行上传。不过对客户端来说可能会重新连接,这个时候你自己就要判断处理了。我也没具体经验,只是说说想法而已,可能并不成熟。
 
也许我问的不好回答,那么把问题细化一下,一个一个解决。
先来讨论第一步,传送文件时直接用TFileStream.Create(FileName, fmOpenRead);打开文件是否合适。
我考虑过把文件复制一个,再慢慢传送给客户端,服务端更新不会影响传送,只是有多少个客户端下载,就会复制多少个文件,可能占很多空间,后面的处理也很麻烦。

备注:服务端的更新不是上传,而是服务器上的另一个程序直接复制新文件覆盖原文件。
 
http://www.51zhan.com 最好的网址站
http://www.51zhan.com 最好的网址站
http://www.51zhan.com 最好的网址站
 
http://www.51zhan.com 最好的网址站
http://www.51zhan.com 最好的网址站
http://www.51zhan.com 最好的网址站
 
没有人做过这样的程序吗?

做过网络传文件程序的都来说一下,你们传送文件的时候怎么打开文件的
 
也不留下email,
贴代码了
unit FrmMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, ExtCtrls, Buttons, ActnList,
ImgList, Menus, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdFTP,IdFTPList, FileCtrl;

type
TFMain = class(TForm)
GroupBox1: TGroupBox;
EditFTPAddr: TLabeledEdit;
EditPortNum: TLabeledEdit;
EditUserName: TLabeledEdit;
EditPassWord: TLabeledEdit;
MemoMsg: TMemo;
QueueList: TListView;
Splitter1: TSplitter;
Splitter2: TSplitter;
ActionList1: TActionList;
GroupBox2: TGroupBox;
GroupBox3: TGroupBox;
Splitter3: TSplitter;
Panel1: TPanel;
Panel2: TPanel;
RemoteFileList: TListView;
ComboHistory: TComboBox;
ImageList1: TImageList;
PopLocal: TPopupMenu;
PopRemote: TPopupMenu;
SiteManage: TAction;
QuickConnect: TAction;
ReConnect: TAction;
DisConnect: TAction;
ViewIcon: TAction;
ViewSmallIcon: TAction;
ViewList: TAction;
ViewReport: TAction;
General: TAction;
Advanced: TAction;
Upload: TAction;
DownLoad: TAction;
QueueAdd: TAction;
QueueDel: TAction;
QueueDelAll: TAction;
ResetStatus: TAction;
QueueSave: TAction;
QueueLoad: TAction;
QueueMoveTop: TAction;
QueueMoveBotton: TAction;
QueueMoveUP: TAction;
QueueMoveDown: TAction;
ToggleLocal: TAction;
ToggleRemote: TAction;
ToggleLog: TAction;
ToggleQueue: TAction;
CopyToClipBoard: TAction;
HelpAbout: TAction;
HelpHelp: TAction;
WriteToMe: TAction;
Registe: TAction;
LocalMakeDir: TAction;
LocalDel: TAction;
Quit: TAction;
N62: TMenuItem;
N63: TMenuItem;
N64: TMenuItem;
N67: TMenuItem;
shu1: TMenuItem;
N68: TMenuItem;
N69: TMenuItem;
N70: TMenuItem;
N71: TMenuItem;
N85: TMenuItem;
RemoteChangeDir: TAction;
RemoteNewDir: TAction;
RemoteDel: TAction;
RemoteRename: TAction;
RemoteUpDir: TAction;
LocalDirUp: TAction;
FTPClient: TIdFTP;
N86: TMenuItem;
N87: TMenuItem;
N88: TMenuItem;
N89: TMenuItem;
N92: TMenuItem;
N93: TMenuItem;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
LocalFileList: TListView;
DriveComboBox1: TDriveComboBox;
LocalChangeDir: TAction;
procedure QuickConnectExecute(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure RemoteChangeDirExecute(Sender: TObject);
procedure RemoteFileListDblClick(Sender: TObject);
procedure RemoteUpDirExecute(Sender: TObject);
procedure DownLoadExecute(Sender: TObject);
procedure UploadExecute(Sender: TObject);
procedure LocalDirUpExecute(Sender: TObject);
procedure LocalMakeDirExecute(Sender: TObject);
procedure RemoteDelExecute(Sender: TObject);
procedure RemoteNewDirExecute(Sender: TObject);
procedure LocalChangeDirExecute(Sender: TObject);
procedure LocalFileListContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
procedure RemoteFileListContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
procedure DriveComboBox1Change(Sender: TObject);
procedure LocalFileListDblClick(Sender: TObject);
procedure ViewIconExecute(Sender: TObject);
procedure ViewSmallIconExecute(Sender: TObject);
procedure ViewListExecute(Sender: TObject);
procedure ViewReportExecute(Sender: TObject);
private
{ Private declarations }
IsTransParent : Boolean;
LocalPath : String;
public
{ Public declarations }
end;

var
FMain: TFMain;

implementation

{$R *.dfm}

procedure TFMain.QuickConnectExecute(Sender: TObject);
begin
//下面判断是否已经建立连接
if FTPClient.Connected then
begin
if MessageDlg('是否中止当前连接及下载过程?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
try
if IsTransParent then
FTPClient.Abort;
FTPClient.Quit;
Except
ShowMessage('中止当前下载过程出错');
end;
end
else
exit;
end;

try
FTPClient.UserName:=EditUserName.Text;
FTPClient.Password:=EditPassWord.Text;
FTPClient.Host:=EditFTPAddr.Text;
FTPClient.Port:=StrToInt(EditPortNum.Text);
FTPClient.Connect;
DisConnect.Enabled :=true;
MemoMsg.Lines.AddStrings(FTPClient.LoginMsg.Text);
ComboHistory.Clear;
ComboHistory.Items.Add('/');
ComboHistory.ItemIndex :=0;
RemoteChangeDirExecute(Sender);
except
ShowMessage('连接服务器出错');
end;
end;

procedure TFMain.FormCreate(Sender: TObject);
begin
IsTransParent := false;
DisConnect.Enabled := false;
end;



procedure TFMain.RemoteChangeDirExecute(Sender: TObject);
Var
LS: TStringList;
FileCount : Integer;
newItem : TListItem;
FolderCount : Integer;
begin
try
LS := TStringList.Create;
FTPClient.ChangeDir(ComboHistory.Text);
RemoteFileList.Items.Clear;
FTPClient.List(LS);
FolderCount := 0;
for FileCount:=0 to LS.Count - 1 do
begin
if FTPClient.DirectoryListing.Items[FileCount].ItemType = ditDirectory then
begin
newItem := RemoteFileList.Items.Insert(FolderCount);
newItem.ImageIndex := 0;
newItem.subItems.Add('文件夹');
end
else begin
newItem := RemoteFileList.Items.Add;
newItem.ImageIndex := 1;
newItem.subItems.Add('');
end ;
newItem.Caption := FTPClient.DirectoryListing.Items[FileCount].FileName;
newItem.subItems.Add(IntToStr(FTPClient.DirectoryListing.Items[FileCount].Size));
newItem.subItems.Add(DateToStr(FTPClient.DirectoryListing.Items[FileCount].ModifiedDate));
end;
finally
LS.Free;
end;

end;

procedure TFMain.RemoteFileListDblClick(Sender: TObject);
var
FileName : String;
begin
if not FTPClient.Connected Then Exit;
if RemoteFileList.Selected = nil then Exit;

FileName := RemoteFileList.Selected.Caption;
if RemoteFileList.Selected.SubItems[0]='文件夹' then
begin
if ComboHistory.ItemIndex = 0 then
FileName := '/'+FileName
else
FileName := ComboHistory.Items[ComboHistory.ItemIndex]+'/'+FileName;
if ComboHistory.Items.IndexOf(FileName) = -1 then
ComboHistory.Items.Add(FileName);
ComboHistory.ItemIndex := ComboHistory.Items.IndexOf(FileName);
RemoteChangeDirExecute(Sender);
end
else
if MessageDlg('是否下载该文件?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
DownLoadExecute(Sender);
end;

procedure TFMain.RemoteUpDirExecute(Sender: TObject);
begin
//返回上一级目录
if FTPClient.Connected then
begin
FTPClient.ChangeDirUp;
ComboHistory.ItemIndex:= ComboHistory.Items.IndexOf(FtpClient.RetrieveCurrentDir);
RemoteChangeDirExecute(Sender);
end;
end;

procedure TFMain.DownLoadExecute(Sender: TObject);
var
FileName : String;
Item : TListItem;
QueueItem : TListItem;
begin
if not FTPClient.Connected Then Exit;
if RemoteFileList.Selected = nil then Exit;
Item := RemoteFileList.Selected;
QueueList.Clear;
while Item <> nil do
begin
QueueItem := QueueList.Items.Add;
QueueItem.Caption := Item.Caption;
QueueItem.SubItems.Add(LocaLPath);
QueueItem.SubItems.Add(Item.SubItems[1]);
QueueItem.SubItems.Add('<-');
QueueItem.SubItems.Add('');
QueueItem.SubItems.Add(ComboHistory.Text);
Item:=RemoteFileList.GetNextItem(Item,sdAll, [isSelected]);
end;
QueueList.Refresh;

RemoteFileList.Enabled:=false;
ComboHistory.Enabled:=false;
RemoteUpDir.Enabled:=false;
IsTransParent:=True;
try
while QueueList.Items.Count > 0 do
begin
FileName:=QueueList.Items[0].Caption;
QueueList.Items[0].SubItems[3]:='正在下载';
QueueList.Refresh;
if FileExists(FileName) then
begin
if MessageDlg('文件已存在,是否继续', mtConfirmation, [mbYes,mbNo], 0) = mrYes then
FTPClient.Get(FileName, LocalPath+'/'+FileName,false, true)
else FTPClient.Get(FileName, LocalPath+'/'+FileName, true);
end
else
FTPClient.Get(FileName, LocalPath+'/'+FileName, false);
QueueList.items[0].Delete;
QueueList.Refresh;
LocalChangeDirExecute(Sender);
end;
RemoteFileList.Enabled:=True;
ComboHistory.Enabled:=True;
RemoteUpDir.Enabled:=True;
IsTransParent:=False;
except
QueueList.Items[0].SubItems[3]:='错误';
ShowMessage('下载文件错误!');
RemoteFileList.Enabled:=True;
ComboHistory.Enabled:=True;
RemoteUpDir.Enabled:=True;
IsTransParent:=False;
end;
end;

procedure TFMain.UploadExecute(Sender: TObject);
var
FileName : String;
Item : TListItem;
QueueItem : TListItem;
begin
if not FTPClient.Connected Then Exit;
if LocalFileList.Selected = nil then Exit;
Item := LocalFileList.Selected;
QueueList.Clear;
while Item <> nil do
begin
QueueItem := QueueList.Items.Add;
QueueItem.Caption := Item.Caption;
QueueItem.SubItems.Add(LocaLPath);
QueueItem.SubItems.Add(Item.SubItems[1]);
QueueItem.SubItems.Add('->');
QueueItem.SubItems.Add('');
QueueItem.SubItems.Add(ComboHistory.Text);
Item:=LocalFileList.GetNextItem(Item,sdAll, [isSelected]);
end;
QueueList.Refresh;

LocalFileList.Enabled:=false;
DriveComboBox1.Enabled:=false;
RemoteFileList.Enabled:=False;
ComboHistory.Enabled:=false;
RemoteUpDir.Enabled:=false;
IsTransParent:=True;
try
while QueueList.Items.Count > 0 do
begin
FileName:=QueueList.Items[0].Caption;
QueueList.Items[0].SubItems[3]:='正在上传';
QueueList.Refresh;
FTPClient.Put(LocalPath+'/'+FileName, FileName);
RemoteChangeDirExecute(Sender);
QueueList.items[0].Delete;
QueueList.Refresh;;
end;
LocalFileList.Enabled:=True;
DriveComboBox1.Enabled:=True;
RemoteFileList.Enabled:=True;
ComboHistory.Enabled:=True;
RemoteUpDir.Enabled:=True;
IsTransParent:=False;
except
QueueList.Items[0].SubItems[3]:='错误';
ShowMessage('上传文件错误!');
LocalFileList.Enabled:=True;
DriveComboBox1.Enabled:=True;
RemoteFileList.Enabled:=True;
ComboHistory.Enabled:=True;
RemoteUpDir.Enabled:=True;
IsTransParent:=False;
end;
end;

procedure TFMain.LocalDirUpExecute(Sender: TObject);
begin
if length(LocalPath) = 3 then exit;
LocalPath:=LocalPath+'.txt';
LocalPath:=ExtractFileDir(LocalPath);
LocalChangeDirExecute(Sender);
end;

procedure TFMain.LocalMakeDirExecute(Sender: TObject);
var
NewFolder : String;
begin
NewFolder:= InputBox('新建文件夹', '名字', '');
if NewFolder <> '' then
try
CreateDir(NewFolder);
LocalChangeDirExecute(Sender);
except
ShowMessage('创建本地目录错误');
end;
end;

procedure TFMain.RemoteDelExecute(Sender: TObject);
Var
FileName:String;
begin
if not FTPClient.Connected then exit;
if RemoteFileList.Selected = nil then exit;

FileName:= RemoteFileList.Selected.Caption;
if RemoteFileList.Selected.SubItems[0] = '文件夹' then
FTPClient.RemoveDir(FileName)
else
FtpClient.Delete(FileName);
RemoteChangeDirExecute(Sender);
end;

procedure TFMain.RemoteNewDirExecute(Sender: TObject);
var
NewFolder : String;
begin
if not FTPClient.Connected then exit;
NewFolder := InputBox('新建文件夹', '名字', '');
if NewFolder <> '' then
FTPClient.MakeDir(NewFolder);
RemoteChangeDirExecute(Sender);
end;

procedure TFMain.LocalChangeDirExecute(Sender: TObject);
var
sr: TSearchRec;
Item : TListItem;
begin
SetCurrentDir(LocalPath);
LocalFileList.Clear;
if FindFirst('*', faDirectory, sr) = 0 then
begin
repeat
if ((sr.Attr and faDirectory) = sr.Attr) and (sr.Name <> '.') and (sr.Name <> '..') then
begin
Item:=LocalFileList.Items.Add;
Item.ImageIndex:=0;
Item.Caption:=sr.Name;
Item.SubItems.Add('文件夹');
Item.SubItems.Add('');
Item.SubItems.Add(DateTimeToStr(sr.Time));
end;
until FindNext(sr) <> 0;
FindClose(sr);
end;

if FindFirst('*', faArchive, sr) = 0 then
begin
repeat
Item:=LocalFileList.Items.Add;
Item.ImageIndex:=1;
Item.Caption:=sr.Name;
Item.SubItems.Add('');
Item.SubItems.Add(IntToStr(sr.Size));
Item.SubItems.Add(DateTimeToStr(sr.Time));
until FindNext(sr) <> 0;
FindClose(sr);
end;
end;

procedure TFMain.LocalFileListContextPopup(Sender: TObject;
MousePos: TPoint; var Handled: Boolean);
begin
if LocalFileList.Selected = nil then
begin
LocalMakeDir.Enabled:=true;
ViewIcon.Enabled:=true;
ViewSmallIcon.Enabled:=true;
ViewList.Enabled:=True;
ViewReport.Enabled:=True;
UpLoad.Enabled:=False;
end
else begin
LocalMakeDir.Enabled:=False;
ViewIcon.Enabled:=False;
ViewSmallIcon.Enabled:=False;
ViewList.Enabled:=False;
ViewReport.Enabled:=False;
if LocalFileList.Selected.SubItems[0] = '文件夹' then
UpLoad.Enabled:=False
else UpLoad.Enabled:=True
end;
end;

procedure TFMain.RemoteFileListContextPopup(Sender: TObject;
MousePos: TPoint; var Handled: Boolean);
begin
if RemoteFileList.Selected = nil then
begin
RemoteNewDir.Enabled:=True;
N86.Enabled:=True;
ViewIcon.Enabled:=True;
ViewSmallIcon.Enabled:=True;
ViewList.Enabled:=True;
ViewReport.Enabled:=True;
DownLoad.Enabled:=False;
RemoteRename.Enabled:=False;
RemoteDel.Enabled:=False;
end
else begin
RemoteNewDir.Enabled:=False;
N86.Enabled:=false;
ViewIcon.Enabled:=False;
ViewSmallIcon.Enabled:=False;
ViewList.Enabled:=False;
ViewReport.Enabled:=False;
RemoteRename.Enabled:=true;
RemoteDel.Enabled:=True;
if remoteFileList.Selected.SubItems[0] = '文件夹' then
DownLoad.Enabled:=False
else download.Enabled:=True
end;
end;

procedure TFMain.DriveComboBox1Change(Sender: TObject);
begin
LocalPath:= DriveComboBox1.Drive+':/';
LocalChangeDirExecute(Sender);
end;

procedure TFMain.LocalFileListDblClick(Sender: TObject);
var
FileName : String;
begin
if LocalFileList.Selected = nil then Exit;
FileName :=LocalFileList.Selected.Caption;
if LocalFileList.Selected.SubItems[0] = '文件夹' then
begin
if Length(LocalPath)=3 then
LocalPath := LocalPath + FileName
else LocalPath := LocalPath + '/' + FileName;
LocalChangeDirExecute(Sender);
end
else begin
if not FTPClient.Connected Then Exit;
if MessageDlg('是否上传该文件?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
UpLoadExecute(Sender);
end;
end;

procedure TFMain.ViewIconExecute(Sender: TObject);
begin
LocalFileList.ViewStyle:=vsIcon;
// TListView(Sender).ViewStyle:=vsIcon;
end;

procedure TFMain.ViewSmallIconExecute(Sender: TObject);
begin
LocalFileList.ViewStyle:=vsSmallIcon;
end;

procedure TFMain.ViewListExecute(Sender: TObject);
begin
LocalFileList.ViewStyle:=vsList;
end;

procedure TFMain.ViewReportExecute(Sender: TObject);
begin
LocalFileList.ViewStyle:=vsReport;
end;

end.
 
感谢热心的 lisongmagic ,我可能又改错了我的标题,我想要的是FTP服务端的代码。
其实不需要全部的代码,我只想知道FTP有那么多连接同时下载文件,它是如何打开文件开始传送的。
我的邮件地址:tdp1425@126.com
 
肯定要多线程,才能完成同时多文件传输;
我想应该也不难.good luck
 
多人接受答案了。
 
后退
顶部