CopyFile - 保存而不覆盖现有文件
CopyFile - save without overwriting existing file
我在做什么:
- 用户单击按钮,
FileUpload
组件(对话框)启动,他可以
从他的 PC 浏览并加载文件。
- 当他点击确定时,文件以特定的方式保存到磁盘
位置。
- 在保存之前我正在重命名(或者更确切地说,用特定名称保存)他的文件使用一些包含
我之前从一些数据库字段中提取的数据。
因此,无论用户加载文件时文件的名称如何,它都会与他的 Firstname
和 LastName
一起保存到磁盘,这是我从一些字符串变量中获得的。
UniMainModule.foldername
= 包含保存文件的文件夹路径。
UniMainModule.FirstName
= 包含用户的名字
UniMainModule.LastName
= 包含用户的姓氏
因此,文件被保存为 FirstName_LastName.pdf
在磁盘上由 foldername
字符串提供的位置。
这是我正在使用的代码:
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
begin
DestFolder:=UniServerModule.StartPath+'files\'+UniMainModule.foldername+'\';
DestName:=DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName+'.pdf';
CopyFile(PChar(AStream.FileName), PChar(DestName), False);
ModalResult:= mrOk;
end;
据我了解,在 msdn
上阅读了一些关于 CopyFile
的信息后,传递 False
意味着它应该并且将会覆盖现有文件。
如果文件在该位置不存在该名称,没关系,它会被保存。
但是如果用户决定再次使用文件上传并上传新文件,新文件将覆盖之前的文件。因为他们正在用相同的名字保存。
如果文件已经存在(该位置存在具有该确切名称的文件),那么您如何确保它不会被覆盖,但我不知道,它被分配了一个 (1) 在名称或其他内容,保留两个文件?
你有一个文件名,所以使用 FileExists 检查文件是否存在。如果它确实将 (1) 附加到文件名,然后重试。重复增加 n 直到你得到一个不存在的文件名。所以,有点像这样:
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
n : integer;
additional : string;
begin
DestFolder:=UniServerModule.StartPath+'files\'+UniMainModule.foldername+'\';
DestName:=DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName;
n := 0;
additional :='.pdf';
while FileExists( DestName + additional ) do
begin
inc(n);
additional := '(' + intToStr(n) + ')'+'.pdf';
end;
CopyFile(PChar(AStream.FileName), PChar(DestName + additional), False);
ModalResult:= mrOk;
end;
这是我的解决方案
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName, NewName : string;
DestFolder : string;
Cnt: integer;
begin
DestFolder:=UniServerModule.StartPath+'files\'+UniMainModule.foldername+'\';
DestName:=DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName+'.pdf';
if FileExists(DestName) then begin
Cnt:=0;
repeat
Inc(Cnt);
NewName:=Format(DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName+'(%d).pdf',[Cnt]);
until not FileExists(NewName);
DestName:=NewName;
end;
CopyFile(PChar(AStream.FileName), PChar(DestName), False);
ModalResult:= mrOk;
end;
循环调用 CopyFile()
,将其 bFailIfExists
参数设置为 TRUE
,这样如果 CopyFile()
失败并出现 ERROR_FILE_EXISTS
,您可以使用新文件名重试] 错误代码。
例如:
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
n : integer;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
n := 0;
while not CopyFile(PChar(AStream.FileName), PChar(DestFolder + DestName), True) do
begin
if GetLastError() <> ERROR_FILE_EXISTS then
begin
// error handling...
Break;
end;
Inc(n);
DestName := UniMainModule.FirstName + '_' + UniMainModule.LastName + ' (' + IntToStr(n) + ').pdf';
end;
ModalResult := mrOk;
end;
但是,与其手动处理,不如让 OS 为您完成。特别是因为 OS 有自己的方式来重命名复制的文件,并且命名方案可以从一个 OS 版本更改(并且已经)到另一个版本。
不使用 CopyFile()
,而是使用 SHFileOperation()
,它有一个 FOF_RENAMEONCOLLISION
标志:
Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists at the destination.
例如:
uses
..., Winapi.ShellAPI;
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
fo : TSHFileOpStruct;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := DestFolder + UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
ZeroMemory(@fo, SizeOf(fo));
fo.Wnd := Handle;
fo.wFunc := FO_COPY;
fo.pFrom := PChar(AStream.FileName+#0);
fo.pTo := PChar(DestName+#0);
fo.fFlags := FOF_SILENT or FOF_NOCONFIRMATION or FOF_NOERRORUI or FOF_NOCONFIRMMKDIR or FOF_RENAMEONCOLLISION;
if SHFileOperation(fo) <> 0 then
begin
// error handling...
end
else if fo.fAnyOperationsAborted then
begin
// abort handling ...
end;
ModalResult := mrOk;
end;
如果您需要知道 OS 为重命名的文件名选择了什么,还有一个 FOF_WANTMAPPINGHANDLE
标志:
If FOF_RENAMEONCOLLISION is specified and any files were renamed, assign a name mapping object that contains their old and new names to the hNameMappings
member. This object must be freed using SHFreeNameMappings
when it is no longer needed.
例如:
uses
..., Winapi.ShellAPI;
type
PHandleToMappings = ^THandleToMappings;
THandleToMappings = record
uNumberOfMappings: UINT; // Number of mappings in the array.
lpSHNameMappings: array[0..0] of PSHNAMEMAPPINGW; // array of pointers to mappings.
end;
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
fo : TSHFileOpStruct;
pMappings : PHandleToMappings;
pMapping : PSHNAMEMAPPINGW;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := DestFolder + UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
ZeroMemory(@fo, SizeOf(fo));
fo.Wnd := Handle;
fo.wFunc := FO_COPY;
fo.pFrom := PChar(AStream.FileName+#0);
fo.pTo := PChar(DestName+#0);
fo.fFlags := FOF_SILENT or FOF_NOCONFIRMATION or FOF_NOERRORUI or FOF_NOCONFIRMMKDIR or FOF_RENAMEONCOLLISION or FOF_WANTMAPPINGHANDLE;
if SHFileOperation(fo) <> 0 then
begin
// error handling...
end else
begin
if fo.fAnyOperationsAborted then
begin
// abort handling...
end;
if fo.hNameMappings <> nil then
begin
try
pMappings := PHandleToMappings(fo.hNameMappings);
pMapping := pMappings^.lpSHNameMappings[0];
SetString(DestName, pMapping^.pszNewPath, pMapping^.cchNewPath);
finally
SHFreeNameMappings(THandle(fo.hNameMappings));
end;
// use DestName as needed...
end;
end;
ModalResult := mrOk;
end;
在 Vista 及更高版本上,您可以选择使用 IFileOperation.CopyItem()
instead, which also supports renaming an item on collision. An IFileOperationProgressSink
如果发生重命名冲突,回调可用于发现新文件名。
例如:
uses
..., Winapi.ActiveX, Winapi.ShlObj, System.Win.Comobj;
type
TMyCopyProgressSink = class(TInterfacedObject, IFileOperationProgressSink)
public
CopiedName: string;
function StartOperations: HResult; stdcall;
function FinishOperations(hrResult: HResult): HResult; stdcall;
function PreRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
function PostRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR; hrRename: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
function PostMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrMove: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
function PostCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrCopy: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreDeleteItem(dwFlags: DWORD; const psiItem: IShellItem): HResult; stdcall;
function PostDeleteItem(dwFlags: DWORD; const psiItem: IShellItem; hrDelete: HResult;
const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
function PostNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR; pszTemplateName: LPCWSTR; dwFileAttributes: DWORD;
hrNew: HResult; const psiNewItem: IShellItem): HResult; stdcall;
function UpdateProgress(iWorkTotal: UINT; iWorkSoFar: UINT): HResult; stdcall;
function ResetTimer: HResult; stdcall;
function PauseTimer: HResult; stdcall;
function ResumeTimer: HResult; stdcall;
end;
function TMyCopyProgressSink.StartOperations: HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.FinishOperations(hrResult: HResult): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR; hrRename: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrMove: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrCopy: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
CopiedName := pszNewName;
Result := S_OK;
end;
function TMyCopyProgressSink.PreDeleteItem(dwFlags: DWORD; const psiItem: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostDeleteItem(dwFlags: DWORD; const psiItem: IShellItem; hrDelete: HResult;
const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR; pszTemplateName: LPCWSTR; dwFileAttributes: DWORD;
hrNew: HResult; const psiNewItem: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.UpdateProgress(iWorkTotal: UINT; iWorkSoFar: UINT): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.ResetTimer: HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PauseTimer: HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.ResumeTimer: HResult; stdcall;
begin
Result := S_OK;
end;
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
pfo : IFileOperation;
psiFrom : IShellItem;
psiTo : IShellItem;
Sink : IFileOperationProgressSink;
bAborted : BOOL;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
try
OleCheck(SHCreateItemFromParsingName(PChar(AStream.FileName), nil, IShellItem, psiFrom));
OleCheck(SHCreateItemFromParsingName(PChar(DestFolder), nil, IShellItem, psiTo));
OleCheck(CoCreateInstance(CLSID_FileOperation, nil, CLSCTX_ALL, IFileOperation, pfo));
OleCheck(pfo.SetOperationFlags(FOF_SILENT or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR or FOF_NOERRORUI or FOF_RENAMEONCOLLISION or FOFX_PRESERVEFILEEXTENSIONS));
Sink := TMyCopyProgressSink.Create;
OleCheck(pfo.CopyItem(psiFrom, psiTo, PChar(DestName), Sink));
OleCheck(pfo.PerformOperations());
pfo.GetAnyOperationsAborted(bAborted);
if bAborted then
begin
// abort handling...
end;
DestName := TMyCopyProgressSink(Sink).CopiedName;
// use DestName as needed...
except
// error handling...
end;
end;
我在做什么:
- 用户单击按钮,
FileUpload
组件(对话框)启动,他可以 从他的 PC 浏览并加载文件。 - 当他点击确定时,文件以特定的方式保存到磁盘 位置。
- 在保存之前我正在重命名(或者更确切地说,用特定名称保存)他的文件使用一些包含 我之前从一些数据库字段中提取的数据。
因此,无论用户加载文件时文件的名称如何,它都会与他的 Firstname
和 LastName
一起保存到磁盘,这是我从一些字符串变量中获得的。
UniMainModule.foldername
= 包含保存文件的文件夹路径。
UniMainModule.FirstName
= 包含用户的名字
UniMainModule.LastName
= 包含用户的姓氏
因此,文件被保存为 FirstName_LastName.pdf
在磁盘上由 foldername
字符串提供的位置。
这是我正在使用的代码:
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
begin
DestFolder:=UniServerModule.StartPath+'files\'+UniMainModule.foldername+'\';
DestName:=DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName+'.pdf';
CopyFile(PChar(AStream.FileName), PChar(DestName), False);
ModalResult:= mrOk;
end;
据我了解,在 msdn
上阅读了一些关于 CopyFile
的信息后,传递 False
意味着它应该并且将会覆盖现有文件。
如果文件在该位置不存在该名称,没关系,它会被保存。
但是如果用户决定再次使用文件上传并上传新文件,新文件将覆盖之前的文件。因为他们正在用相同的名字保存。
如果文件已经存在(该位置存在具有该确切名称的文件),那么您如何确保它不会被覆盖,但我不知道,它被分配了一个 (1) 在名称或其他内容,保留两个文件?
你有一个文件名,所以使用 FileExists 检查文件是否存在。如果它确实将 (1) 附加到文件名,然后重试。重复增加 n 直到你得到一个不存在的文件名。所以,有点像这样:
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
n : integer;
additional : string;
begin
DestFolder:=UniServerModule.StartPath+'files\'+UniMainModule.foldername+'\';
DestName:=DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName;
n := 0;
additional :='.pdf';
while FileExists( DestName + additional ) do
begin
inc(n);
additional := '(' + intToStr(n) + ')'+'.pdf';
end;
CopyFile(PChar(AStream.FileName), PChar(DestName + additional), False);
ModalResult:= mrOk;
end;
这是我的解决方案
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName, NewName : string;
DestFolder : string;
Cnt: integer;
begin
DestFolder:=UniServerModule.StartPath+'files\'+UniMainModule.foldername+'\';
DestName:=DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName+'.pdf';
if FileExists(DestName) then begin
Cnt:=0;
repeat
Inc(Cnt);
NewName:=Format(DestFolder+UniMainModule.FirstName+'_'+UniMainModule.LastName+'(%d).pdf',[Cnt]);
until not FileExists(NewName);
DestName:=NewName;
end;
CopyFile(PChar(AStream.FileName), PChar(DestName), False);
ModalResult:= mrOk;
end;
循环调用 CopyFile()
,将其 bFailIfExists
参数设置为 TRUE
,这样如果 CopyFile()
失败并出现 ERROR_FILE_EXISTS
,您可以使用新文件名重试] 错误代码。
例如:
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
n : integer;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
n := 0;
while not CopyFile(PChar(AStream.FileName), PChar(DestFolder + DestName), True) do
begin
if GetLastError() <> ERROR_FILE_EXISTS then
begin
// error handling...
Break;
end;
Inc(n);
DestName := UniMainModule.FirstName + '_' + UniMainModule.LastName + ' (' + IntToStr(n) + ').pdf';
end;
ModalResult := mrOk;
end;
但是,与其手动处理,不如让 OS 为您完成。特别是因为 OS 有自己的方式来重命名复制的文件,并且命名方案可以从一个 OS 版本更改(并且已经)到另一个版本。
不使用 CopyFile()
,而是使用 SHFileOperation()
,它有一个 FOF_RENAMEONCOLLISION
标志:
Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists at the destination.
例如:
uses
..., Winapi.ShellAPI;
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
fo : TSHFileOpStruct;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := DestFolder + UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
ZeroMemory(@fo, SizeOf(fo));
fo.Wnd := Handle;
fo.wFunc := FO_COPY;
fo.pFrom := PChar(AStream.FileName+#0);
fo.pTo := PChar(DestName+#0);
fo.fFlags := FOF_SILENT or FOF_NOCONFIRMATION or FOF_NOERRORUI or FOF_NOCONFIRMMKDIR or FOF_RENAMEONCOLLISION;
if SHFileOperation(fo) <> 0 then
begin
// error handling...
end
else if fo.fAnyOperationsAborted then
begin
// abort handling ...
end;
ModalResult := mrOk;
end;
如果您需要知道 OS 为重命名的文件名选择了什么,还有一个 FOF_WANTMAPPINGHANDLE
标志:
If FOF_RENAMEONCOLLISION is specified and any files were renamed, assign a name mapping object that contains their old and new names to the
hNameMappings
member. This object must be freed usingSHFreeNameMappings
when it is no longer needed.
例如:
uses
..., Winapi.ShellAPI;
type
PHandleToMappings = ^THandleToMappings;
THandleToMappings = record
uNumberOfMappings: UINT; // Number of mappings in the array.
lpSHNameMappings: array[0..0] of PSHNAMEMAPPINGW; // array of pointers to mappings.
end;
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
fo : TSHFileOpStruct;
pMappings : PHandleToMappings;
pMapping : PSHNAMEMAPPINGW;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := DestFolder + UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
ZeroMemory(@fo, SizeOf(fo));
fo.Wnd := Handle;
fo.wFunc := FO_COPY;
fo.pFrom := PChar(AStream.FileName+#0);
fo.pTo := PChar(DestName+#0);
fo.fFlags := FOF_SILENT or FOF_NOCONFIRMATION or FOF_NOERRORUI or FOF_NOCONFIRMMKDIR or FOF_RENAMEONCOLLISION or FOF_WANTMAPPINGHANDLE;
if SHFileOperation(fo) <> 0 then
begin
// error handling...
end else
begin
if fo.fAnyOperationsAborted then
begin
// abort handling...
end;
if fo.hNameMappings <> nil then
begin
try
pMappings := PHandleToMappings(fo.hNameMappings);
pMapping := pMappings^.lpSHNameMappings[0];
SetString(DestName, pMapping^.pszNewPath, pMapping^.cchNewPath);
finally
SHFreeNameMappings(THandle(fo.hNameMappings));
end;
// use DestName as needed...
end;
end;
ModalResult := mrOk;
end;
在 Vista 及更高版本上,您可以选择使用 IFileOperation.CopyItem()
instead, which also supports renaming an item on collision. An IFileOperationProgressSink
如果发生重命名冲突,回调可用于发现新文件名。
例如:
uses
..., Winapi.ActiveX, Winapi.ShlObj, System.Win.Comobj;
type
TMyCopyProgressSink = class(TInterfacedObject, IFileOperationProgressSink)
public
CopiedName: string;
function StartOperations: HResult; stdcall;
function FinishOperations(hrResult: HResult): HResult; stdcall;
function PreRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
function PostRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR; hrRename: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
function PostMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrMove: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
function PostCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrCopy: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreDeleteItem(dwFlags: DWORD; const psiItem: IShellItem): HResult; stdcall;
function PostDeleteItem(dwFlags: DWORD; const psiItem: IShellItem; hrDelete: HResult;
const psiNewlyCreated: IShellItem): HResult; stdcall;
function PreNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
function PostNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR; pszTemplateName: LPCWSTR; dwFileAttributes: DWORD;
hrNew: HResult; const psiNewItem: IShellItem): HResult; stdcall;
function UpdateProgress(iWorkTotal: UINT; iWorkSoFar: UINT): HResult; stdcall;
function ResetTimer: HResult; stdcall;
function PauseTimer: HResult; stdcall;
function ResumeTimer: HResult; stdcall;
end;
function TMyCopyProgressSink.StartOperations: HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.FinishOperations(hrResult: HResult): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostRenameItem(dwFlags: DWORD; const psiItem: IShellItem;
pszNewName: LPCWSTR; hrRename: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostMoveItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrMove: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostCopyItem(dwFlags: DWORD; const psiItem: IShellItem;
const psiDestinationFolder: IShellItem; pszNewName: LPCWSTR;
hrCopy: HResult; const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
CopiedName := pszNewName;
Result := S_OK;
end;
function TMyCopyProgressSink.PreDeleteItem(dwFlags: DWORD; const psiItem: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostDeleteItem(dwFlags: DWORD; const psiItem: IShellItem; hrDelete: HResult;
const psiNewlyCreated: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PreNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PostNewItem(dwFlags: DWORD; const psiDestinationFolder: IShellItem;
pszNewName: LPCWSTR; pszTemplateName: LPCWSTR; dwFileAttributes: DWORD;
hrNew: HResult; const psiNewItem: IShellItem): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.UpdateProgress(iWorkTotal: UINT; iWorkSoFar: UINT): HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.ResetTimer: HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.PauseTimer: HResult; stdcall;
begin
Result := S_OK;
end;
function TMyCopyProgressSink.ResumeTimer: HResult; stdcall;
begin
Result := S_OK;
end;
procedure TsomeForm.UniFileUpload1Completed(Sender: TObject; AStream: TFileStream);
var
DestName : string;
DestFolder : string;
pfo : IFileOperation;
psiFrom : IShellItem;
psiTo : IShellItem;
Sink : IFileOperationProgressSink;
bAborted : BOOL;
begin
DestFolder := UniServerModule.StartPath + 'files\' + UniMainModule.foldername + '\';
DestName := UniMainModule.FirstName + '_' + UniMainModule.LastName + '.pdf';
try
OleCheck(SHCreateItemFromParsingName(PChar(AStream.FileName), nil, IShellItem, psiFrom));
OleCheck(SHCreateItemFromParsingName(PChar(DestFolder), nil, IShellItem, psiTo));
OleCheck(CoCreateInstance(CLSID_FileOperation, nil, CLSCTX_ALL, IFileOperation, pfo));
OleCheck(pfo.SetOperationFlags(FOF_SILENT or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR or FOF_NOERRORUI or FOF_RENAMEONCOLLISION or FOFX_PRESERVEFILEEXTENSIONS));
Sink := TMyCopyProgressSink.Create;
OleCheck(pfo.CopyItem(psiFrom, psiTo, PChar(DestName), Sink));
OleCheck(pfo.PerformOperations());
pfo.GetAnyOperationsAborted(bAborted);
if bAborted then
begin
// abort handling...
end;
DestName := TMyCopyProgressSink(Sink).CopiedName;
// use DestName as needed...
except
// error handling...
end;
end;