Thanks.
Helaas werkt het omzetten van een dergelijke filehandle naar een filename niet. Dus helaas nog geen oplossing voor het rechtstreeks schrijven van Word-documenten naar de database.
Enfin, voor de geïnteresseerden, hierbij de GetFileNameFromHandle functie:
Delphi Code:
uses
Windows, PsAPI, SysUtils;
function GetFileNameFromHandle(Handle: HFILE): String;
var
FileName: array[0..MAX_PATH] of Char;
Mapping: HLOCAL;
FileSizeHi: Integer;
FileSizeLo: Integer;
View: Pointer;
Drives: array[0..128] of Char;
PDrive: PChar;
Device: array[0..MAX_PATH] of Char;
begin
Result := '';
FileSizeHi := 0;
FileSizeLo := GetFileSize(Handle, @FileSizeHi);
if (FileSizeHi <> 0) or (FileSizeLo <> 0) then
begin
Mapping := CreateFileMapping(Handle, nil, PAGE_READONLY, 0, 1, nil);
if Mapping <> 0 then
try
View := MapViewOfFile(Mapping, FILE_MAP_READ, 0, 0, 1);
if View <> nil then
try
if GetMappedFileName(GetCurrentProcess, View, FileName,
MAX_PATH) <> 0 then
begin
Result := FileName;
if GetLogicalDriveStrings(SizeOf(Drives), Drives) <> 0 then
begin
PDrive := Drives;
while PDrive^ <> #0 do
begin
PDrive[2] := #0;
if QueryDosDevice(PDrive, Device, MAX_PATH) <> 0 then
if AnsiStrLIComp(FileName, Device, StrLen(Device)) = 0 then
begin
Result := StringReplace(FileName, Device, PDrive,
[rfIgnoreCase]);
Break;
end;
Inc(PDrive, 4);
end;
end;
end;
finally
UnmapViewOfFile(View);
end;
finally
CloseHandle(Mapping);
end;
end;
end;
En de ongetwijfeld iets nuttigere functie om een bestand in een FILESTREAM-kolom te pompen:
Delphi Code:
function InsertSqlDocument(var Id: Integer; const FileName: String;
Connection: TADOConnection): Boolean;
const
InsertSQL = 'INSERT INTO Documents (Id, FileName) VALUES (:Id, :FileName)';
SelectSQL = 'SELECT GET_FILESTREAM_TRANSACTION_CONTEXT(), Doc.PathName() ' +
'FROM Documents WHERE Id = :Id';
BlockSize = 1024 * 512;
var
CloseConn: Boolean;
DataSet: TADOQuery;
Context: array[0..127] of Byte;
FilePath: WideString;
FileHandle: HFILE;
Source: TStream;
Dest: TStream;
Buffer: array[0..BlockSize - 1] of Char;
ReadCount: Integer;
begin
Result := False;
CloseConn := not Connection.Connected;
DataSet := TADOQuery.Create(nil);
try
if FileExists(FileName) then
try
Connection.Open;
Connection.BeginTrans;
if Id = -1 then
Id := GetNewRecordId(Connection);
DataSet.Connection := Connection;
DataSet.SQL.Text := InsertSQL;
DataSet.Parameters.ParamValues['Id'] := Id;
DataSet.Parameters.ParamValues['FileName'] := ExtractFileName(FileName);
DataSet.ExecSQL;
DataSet.SQL.Text := SelectSQL;
DataSet.Parameters.ParamValues['Id'] := Id;
DataSet.Open;
if not DataSet.Eof then
begin
DataSet.Fields[0].GetData(@Context);
FilePath := DataSet.Fields[1].Value;
DataSet.Close;
FileHandle := OpenSqlFilestream(PWideChar(FilePath),
SQL_FILESTREAM_READWRITE, 0, @Context[2], Context[0], nil);
if FileHandle <> INVALID_HANDLE_VALUE then
begin
Source := TFileStream.Create(FileName, fmOpenRead);
Dest := TFileStream.Create(FileHandle);
try
repeat
ReadCount := Source.Read(Buffer, SizeOf(Buffer));
Dest.Write(Buffer, ReadCount);
until ReadCount <= 0;
finally
Dest.Free; //Implicitly closes FileHandle
Source.Free;
end;
Connection.CommitTrans;
Result := True;
end
else
RaiseLastOSError;
end;
except
Connection.RollbackTrans;
raise;
end;
finally
DataSet.Free;
if CloseConn then
Connection.Close;
end;
end;
Bookmarks