Question

Dans ma demande mes utilisateurs peuvent importer des fichiers (pdf / xls / doc) à une table ou les exporter vers un dossier. Maintenant, je veux ouvrir directement ces fichiers.

Jusqu'à présent, je suis en mesure de: - obtenir un nom unique - enregistrer le fichier dans le blob fichier généré - ouvrir

Le problème est que je ne sais pas comment supprimer (ou mise à jour) le fichier après que le dossier sera fermé par l'utilisateur.

Je serai très heureux si quelqu'un peut me aider à ce sujet:)

Voici un aperçu de mon 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;
Était-ce utile?

La solution

Malheureusement, il y a 4 upvotes en ce moment pour cette réponse par Remy Lebeau , quand la technique ne fonctionnera pas avec la plupart des applications. Peut-être l'un des upvoters pourrait publier un extrait de code qui permet d'ouvrir un fichier PDF avec Acrobat Reader alors que le fichier est toujours ouvert avec le drapeau de FILE_FLAG_DELETE_ON_CLOSE?

Quoi qu'il en soit, vous pouvez combiner quelques-uns des conseils ici pour obtenir les meilleurs résultats:

  • Avoir une liste interne des fichiers temporaires par votre application.
  • Lors de l'arrêt du programme de marche la liste des fichiers temporaires et essayer de les supprimer. Si cela ne fonctionne pas pour certains d'entre eux (parce qu'ils sont encore ouverts dans l'application externe) pour enregistrer ces suppression au redémarrage avec le Gabr code vous a donné .
  • Chaque fois que vous avez besoin d'un nouveau fichier temporaire, d'abord marcher votre liste interne des fichiers et essayer de réutiliser l'un d'eux. Créer un nouveau fichier (et ajouter son nom à la liste) que si cela ne fonctionne pas.

Je préfère cette approche pour enregistrer tous les fichiers pour la suppression au redémarrage, parce que je ne suis pas sûr combien de fichiers temporaires de votre application peut ouvrir - peut-être il y a une limite pour le nombre de fichiers qui peuvent être enregistrés avec MOVEFILE_DELAY_UNTIL_REBOOT? Il est une ressource système à l'échelle, j'utiliser avec parcimonie.

Autres conseils

Une possibilité serait d'ajouter chaque fichier temporaire à la liste des fichiers qui sont supprimés lors du démarrage du système.

vous pouvez simplement appeler sur la plate-forme Windows NT (depuis Windows 2000), la fonction de MoveFileEx avec un second paramètre (destination) fixé à zéro et avec un MOVEFILE_DELAY_UNTIL_REBOOT du pavillon.

Sous Windows 9x, ce qui est beaucoup plus compliqué. Vous devez modifier le fichier% windir% \ wininit.ini et écrire une entrée dans la section [Renommer].

Comment faire pour déplacer des fichiers qui sont actuellement en cours d'utilisation décrit les techniques.

Fonction DSiMoveOnReboot (partie de la libre DSiWin32 bibliothèque) gère les deux systèmes d'exploitation. Si vous passez une chaîne vide comme second paramètre, il supprimera le fichier source au redémarrage.

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 }

Utilisez la fonction API Win32 CreateFile () pour ouvrir le fichier, en spécifiant le drapeau FILE_FLAG_DELETE_ON_CLOSE, puis passer la poignée résultante à un objet THandleStream afin que vous pouvez toujours utiliser SaveToStream ().

En outre, il y a un bug dans votre code - vous passez le mauvais type de poignée à ShellExecute (). Il attend une poignée de fenêtre, mais vous passez un descripteur de fichier à la place, et pire encore, vous accédez à la poignée de fichiers après avoir déjà libéré le TFileStream, fermant ainsi la poignée.

Peut-être que vous pouvez les stocker dans un certain bien connu pour vous le dossier (par exemple dans le dossier sous-dossier TEMP avec un nom de votre application) et des contenus clairs de ce dossier whem charge la prochaine fois que l'utilisateur de votre application? Ou vous pouvez installer l'utilitaire clair et définir son fonctionnement en démarrage automatique.
Encore une idée de compensation des fichiers après le redémarrage - vous pouvez effacer tout dans votre sous-dossier au démarrage, ou de faire une liste des fichiers créés avec la dernière fois modifier, dernière taille, stocker cette liste dans le fichier XML, puis supprimer ou mettre à jour la comparaison contenu de votre sous-dossier temporaire avec les détails du fichier de cette liste?

Si je me souviens bien, il y a un drapeau pour CreateFile qui indique à Windows qu'il doit supprimer le fichier une fois la dernière poignée il a été fermé. Alors, créez le fichier normalement, fermer et rouvrir avec une part refuser aucune et le drapeau mentionné ci-dessus. Ensuite, laissez l'application externe ouvrir et fermer vous-même. Cela devrait se traduire dans Windows de supprimer le fichier une fois l'application externe ferme.

(je ne l'ai pas essayé.)

Unix comme OS l'astuce habituelle consiste à ouvrir et supprimer immédiatement. il ne sera pas apparaître sur le répertoire, mais les données sont encore affectées au processus (es) qui la maintiennent ouverte. dès qu'elle est fermée (soit bien de par la mort de processus), le système de fichiers ne récupérer l'espace.

ce n'est pas un hack, il est documenté et soutenu (conséquence d'avoir le nombre handles de fichiers ouverts comme une « référence » au fichier, tout comme les entrées du répertoire).

peut-être il y a un truc similaire sur les fenêtres? Je crois me rappeler que NTFS prend en charge plusieurs références au même fichier (pas, les raccourcis ne sont pas ceux). le cas échéant, la suppression du fichier mais toujours accroché à la dernière référence en tant que ressource éphémère pourrait fonctionner.

De toute évidence, je suis juste spéculant ici ...

En fait, notre application de créer des fichiers dans un dossier temp spécifique dans. Lorsque l'application Fermez les fies sont supprimés. Si l'application ne se ferme pas correctement, la prochaine exécution (quand fermer) tous les fichiers sont supprimés.

En outre, vous pouvez lancer un processus d'arrière-plan pour supprimer les fichiers qui ne sont plus ouverts. Shellexecute retourner une poignée (associer en interne cette poignée à un FileName). Ce processus d'arrière-plan doit tester la poignée de processus qui n'existe et supprimer les fichiers associés.

Excuse pour mauvais anglais. ; -)

Cordialement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top