簡體   English   中英

在Delphi XE6中調用datasnap服務器方法后刪除文件

[英]File delete after datasnap server method call in Delphi XE6

我有一個用Delphi XE6編寫的Datasnap客戶端服務器應用程序。 我正在調用一個使用TFileStream創建臨時文件的服務器方法,用我的http帖子中的TStream格式填充我的報告,並將其返回給我的客戶端。 這一切都按需要運作。 但是,在方法結束時,我調用deleteFile方法從服務器中刪除臨時文件,但它永遠不會被刪除。 我究竟做錯了什么?

var
  r,f: String;
  SS: TStringStream;
  Uid: TGuid;
begin
   CreateGuid(Uid);
   f:= ChangeFileExt(GuidToString(Uid),'.rpt');
   result:= TFileStream.Create(f, fmCreate or fmOpenWrite);

  r := getRunReportJSON(ARunReportObj);
  SS := TStringStream.Create(r, TEncoding.ASCII);
  try
    try      
      ServerContainer1.idHttp1.Post(gUrl, SS, result);
      Result.Position:= 0;
    except
    end;
  finally
    SS.Free;
    if FileExists(f) then
      DeleteFile(f)
  end;
end;

在銷毀文件流對象之前,無法刪除您創建的文件流。 文件流對象包裝文件句柄,當文件句柄存在時,不能刪除其后面的文件對象。

您需要先刪除文件流對象,然后才能刪除它。

您的代碼有一些奇怪的異常處理。 它在函數中間不受歧視地吞下異常。 你真的想要如此野蠻嗎? 在try / except塊之外,任何異常都會導致文件流對象泄露。

在刪除之前測試文件是否存在並沒有多大意義。 如果您成功創建了文件流,那么您可以確信該文件存在。

正如David所說,在TFileStream首先被銷毀之前你無法刪除文件,所以它可以關閉文件的句柄。 如果您希望在使用服務器完成后自動刪除文件,您可以:

  1. 直接使用Win32 CreateFile()函數打開文件,以便指定FILE_FLAG_DELETE_ON_CLOSE標志,然后使用THandleStream類包裝生成的句柄。

     type TMyHandleStream = class(THandleStream) public destructor Destroy; override; end; destructor TMyHandleStream.Destroy; begin inherited; CloseHandle(Handle); end; var h: THandle; r, f: String; SS: TStringStream; Uid: TGuid; begin CreateGuid(Uid); f := 'C:\\some folder\\' + GuidToString(Uid) + '.rpt'; h := Windows.CreateFile(PChar(f), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0); if h = INVALID_HANDLE_VALUE then RaiseLastOSError; Result := TMyHandleStream.Create(h); try r := getRunReportJSON(ARunReportObj); SS := TStringStream.Create(r, TEncoding.ASCII); try ServerContainer1.IdHTTP1.Post(gUrl, SS, Result); finally SS.Free; end; Result.Position := 0; except Result.Free; raise; end; end; 
  2. TFileStream派生一個新類並覆蓋其析構函數以刪除該文件:

     type TMyFileStream = class(TFileStream) public destructor Destroy; override; end; destructor TMyFileStream.Destroy; begin inherited; DeleteFile(Self.FileName); end; 

     var r, f: String; SS: TStringStream; Uid: TGuid; begin CreateGuid(Uid); f := 'C:\\some folder\\' + GuidToString(Uid) + '.rpt'; Result := TMyFileStream.Create(f, fmCreate or fmOpenReadWrite); try r := getRunReportJSON(ARunReportObj); SS := TStringStream.Create(r, TEncoding.ASCII); try ServerContainer1.IdHTTP1.Post(gUrl, SS, Result); finally SS.Free; end; Result.Position := 0; except Result.Free; raise; end; end; 
  3. 使用此論壇中顯示的TFileStreamEx回答

     type TFileStreamEx = class(THandleStream) public constructor Create(const FileName: string; Mode: Word; flags: DWORD = FILE_ATTRIBUTE_NORMAL); destructor Destroy; override; end; constructor TFileStreamEx.Create(const FileName: string; Mode: Word; flags: DWORD = FILE_ATTRIBUTE_NORMAL); const AccessMode: array[0..2] of LongWord = ( GENERIC_READ, GENERIC_WRITE, GENERIC_READ or GENERIC_WRITE); ShareMode: array[0..4] of LongWord = ( 0, 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE); begin if Mode = fmCreate then begin inherited Create( CreateFile( PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, flags, 0 ) ); if Handle = INVALID_HANDLE then raise EFCreateError.CreateFmt(SFCreateError, [FileName]); end else begin inherited Create( CreateFile( PChar(FileName), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING, flags, 0 ) ); if Handle = INVALID_HANDLE then raise EFOpenError.CreateFmt(SFOpenError, [FileName]); end; end; destructor TFileStreamEx.Destroy; begin if Handle <> INVALID_HANDLE then CloseHandle(Handle); end; 

     var r, f: String; SS: TStringStream; Uid: TGuid; begin CreateGuid(Uid); f := 'C:\\some folder\\' + GuidToString(Uid) + '.rpt'; Result := TFileStreamEx.Create(f, fmCreate or fmOpenReadWrite, FILE_FLAG_DELETE_ON_CLOSE); try r := getRunReportJSON(ARunReportObj); SS := TStringStream.Create(r, TEncoding.ASCII); try ServerContainer1.IdHTTP1.Post(gUrl, SS, Result); finally SS.Free; end; Result.Position := 0; except Result.Free; raise; end; end; 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM