gpt4 book ai didi

delphi - Delphi XE6 中 datasnap 服务器方法调用后文件删除

转载 作者:行者123 更新时间:2023-12-03 15:41:55 24 4
gpt4 key购买 nike

我有一个用 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;

最佳答案

正如 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. 使用 this forum answer 中所示的 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;

关于delphi - Delphi XE6 中 datasnap 服务器方法调用后文件删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37728036/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com