In my application my users can import files (pdf/xls/doc) to a table or export them to a folder. Now I want to directly open these files.
So far I'm able to : - get an unique name - save the blob file into the generated file - open it
The problem is that I don't know how to delete (or update) the file after that the file will be closed by the user.
I'll be very happy if someone can help me on this :)
Here is a snapshot of my code :
procedure OpenTemporaryFile(AFileExtension: String; AKey: Integer;
AMyConnection: TMyConnection);
Var
qrDocuments : TMyQuery ;
TmpName,ExtName: string;
TempFileName: TFileStream;
begin
//Generate an unique tmp file located into user temp folder
TmpName:= FileGetTempName('~SI');
ExtName:= ChangeFileExt(TmpName, AFileExtension);
//Change files extension so that Shellexecute will be able to open the file
RenameFile(TmpName,ExtName );
//Creating the FileStream (data is fetched from an blob field)
TempFileName := TFileStream.Create(ExtName, fmOpenReadWrite );
qrDocuments := TMyQuery.create(nil);
try
qrDocuments.Connection := AMyConnection;
qrDocuments.Close;
qrDocuments.SQL.Clear;
qrDocuments.SQL.Text:='Select Id,FileName,Data from files where Id = :prId And Data IS NOT NULL';
qrDocuments.ParamByName('prId').AsInteger := AKey;
qrDocuments.open;
TBlobField(qrDocuments.FieldByName('Data')).SaveToStream(TempFileName);
finally
TempFileName.Free;
qrDocuments.free;
end;
ShellExecute(Application.Handle, 'open', Pchar(ExtName), '', '', SW_SHOWNORMAL);
DeleteFile( ExtName);
end;
Unfortunately there are 4 upvotes right now for this answer by Remy Lebeau, when the technique simply won't work with most applications. Maybe one of the upvoters could post a code snippet that allows to open a PDF file with Acrobat Reader while the file is still open with the FILE_FLAG_DELETE_ON_CLOSE
flag?
Anyway, you could combine some of the tips here for best results:
I'd prefer this approach to registering all files for deletion on reboot, because I'm not sure how many temporary files your application might open - maybe there is a limit for the number of files that can be registered with MOVEFILE_DELAY_UNTIL_REBOOT
? It's a system-wide resource I would use only sparingly.
One possibility would be to add each temporary file to the list of files that are deleted during the system startup.
On Windows NT platform (since Windows 2000), you can just call MoveFileEx function with a second parameter (destination) set to nil and with a flag MOVEFILE_DELAY_UNTIL_REBOOT.
On Windows 9x, this is much more complicated. You have to edit file %WINDIR%\wininit.ini and write an entry into the [Rename] section.
MSDN entry How To Move Files That Are Currently in Use describes both techniques.
Function DSiMoveOnReboot (part of the free DSiWin32 library) handles both OSes. If you pass an empty string as the second parameter, it will delete the source file on reboot.
function DSiMoveOnReboot(const srcName, destName: string): boolean;
var
wfile: string;
winit: text;
wline: string;
cont : TStringList;
i : integer;
found: boolean;
dest : PChar;
begin
if destName = '' then
dest := nil
else
dest := PChar(destName);
if DSiIsWinNT then
Result := MoveFileEx(PChar(srcName), dest, MOVEFILE_DELAY_UNTIL_REBOOT)
else
Result := false;
if not Result then begin
// not NT, write a Rename entry to WININIT.INI
wfile := DSiGetWindowsFolder+'\wininit.ini';
if FileOpenSafe(wfile,winit,500,120{one minute}) then begin
try
cont := TStringList.Create;
try
Reset(winit);
while not Eof(winit) do begin
Readln(winit,wline);
cont.Add(wline);
end; //while
if destName = '' then
wline := 'NUL='+srcName
else
wline := destName+'='+srcName;
found := false;
for i := 0 to cont.Count - 1 do begin
if UpperCase(cont[i]) = '[RENAME]' then begin
cont.Insert(i+1,wline);
found := true;
break;
end;
end; //for
if not found then begin
cont.Add('[Rename]');
cont.Add(wline);
end;
Rewrite(winit);
for i := 0 to cont.Count - 1 do
Writeln(winit,cont[i]);
Result := true;
finally cont.Free; end;
finally Close(winit); end;
end;
end;
end; { DSiMoveOnReboot }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With