Pregunta

En mi solicitud mis usuarios pueden importar archivos (pdf / xls / doc) a una tabla o exportarlos a una carpeta. Ahora quiero abrir directamente estos archivos.

Hasta ahora soy capaz de: - obtener un nombre único - guardar el archivo de burbuja en el archivo generado - abrirlo

El problema es que no sé cómo eliminar (o actualizar) el archivo después de que el archivo estará cerrada por el usuario.

Voy a ser muy feliz si alguien me puede ayudar en esto:)

Esta es una instantánea de mi código:

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;
¿Fue útil?

Solución

Por desgracia hay 4 upvotes ahora para esta respuesta por Remy Lebeau , cuando la técnica simplemente no va a funcionar con la mayoría de las aplicaciones. Tal vez una de las upvoters puede publicar un fragmento de código que permite abrir un archivo PDF con Acrobat Reader, mientras que el archivo está todavía abierta con la bandera FILE_FLAG_DELETE_ON_CLOSE?

De todos modos, puede combinar algunos de los consejos aquí para obtener mejores resultados:

  • Tener una lista interna de archivos temporales que utiliza su aplicación.
  • En el apagado programa de caminar por la lista de archivos temporales y tratar de eliminarlos. Si esto no funciona para algunos de ellos (debido a que todavía están abiertas en la aplicación externa) registrarlas para su eliminación en el reinicio con el código gabr te dieron .
  • Siempre que necesite un nuevo archivo temporal, caminar primero de su lista interna de archivos y tratar de volver a utilizar uno de ellos. Crear un nuevo archivo (y añadir su nombre a la lista), si ésta falla.

Yo prefiero este enfoque para incluir todos los archivos para su eliminación en el reinicio, porque no estoy seguro de cuántos archivos temporales de su aplicación podría abrir - tal vez hay un límite para el número de archivos que se pueden registrar con MOVEFILE_DELAY_UNTIL_REBOOT? Es un recurso de todo el sistema me gustaría utilizar con moderación.

Otros consejos

Una posibilidad sería añadir cada archivo temporal a la lista de archivos que se eliminan durante el inicio del sistema.

En la plataforma Windows NT (desde Windows 2000), sólo puede llamar a función MoveFileEx con un segundo parámetro (destino) se establece en cero y con un MOVEFILE_DELAY_UNTIL_REBOOT bandera.

En Windows 9x, esto es mucho más complicado. Tiene que editar el archivo% windir% \ wininit.ini y escribir una entrada en la sección [Renombrar].

Cómo mover archivos que están actualmente en uso describe ambas técnicas.

Función DSiMoveOnReboot (parte de la DSiWin32 biblioteca) se encarga de ambos sistemas operativos. Si pasa una cadena vacía como el segundo parámetro, se eliminará el archivo de origen en el reinicio.

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 }

Utilice la función Win32 API CreateFile () para abrir el archivo, especificando la bandera FILE_FLAG_DELETE_ON_CLOSE, y luego pasar el mango resultante a un objeto THandleStream por lo que todavía puede utilizar SaveToStream ().

Además, hay un error en el código - que está pasando el tipo equivocado de mango a ShellExecute (). Se espera un identificador de ventana, pero que están pasando un identificador de archivo en su lugar, y lo peor está accediendo al identificador de archivo después de que ya haya liberado la TFileStream, cerrando así el mango.

Tal vez se puede almacenar en algún conocido para que la carpeta (por ejemplo subcarpeta en la carpeta TEMP con un nombre de su aplicación) y claro contenido de esta carpeta whem usuario la próxima vez que carga su aplicación? O puede instalar clara utilidad adicional y ponerlo a funcionar en el inicio automático.
Una de las ideas más sobre la eliminación de archivos al iniciar el sistema - puede borrar todo en su subcarpeta en el arranque, o hacer una lista de los archivos que ha creado con la última modificar el tiempo, el último tamaño, almacenar esta lista en el archivo XML y luego borrar o actualizar comparar contenido de la subcarpeta temp con detalles de archivo de esa lista?

Si no recuerdo mal, hay una bandera para CreateFile que indica a Windows que se debe eliminar el archivo una vez que el último identificador para ella ha sido cerrado. Por lo tanto, crear el archivo, normalmente, cerrar y volver a abrirlo con una cuota de negar ninguno y la bandera se ha mencionado anteriormente. Luego dejar que la aplicación externa abrirlo y cerrarlo a sí mismo. Esto debe resultar en la eliminación del archivo de Windows una vez que la aplicación externa cierra.

(No he probado esto.)

en sistemas operativos tipo Unix el truco habitual es abrirlo y eliminar de inmediato. no aparecerá en el directorio, pero los datos aún está asignada al proceso (s) que mantenerla abierta. tan pronto como se cierra (ya sea bien por el proceso de morir), el sistema de archivos podría recuperar el espacio.

no es un truco, que está documentado y apoyado (una consecuencia de tener el archivo abierto como un recuento de 'referencia' al archivo, al igual que las entradas de directorio).

tal vez hay algún truco similar en las ventanas? Me parece recordar que NTFS es compatible con múltiples referencias al mismo archivo (no, accesos directos no son aquellos). si es así, la eliminación del archivo, pero todavía se aferran a la última referencia como un recurso efímero podría funcionar.

Obviamente, sólo estoy especulando aquí ...

En realidad nuestra solicitud de crear archivos en una carpeta temporal especific. Cuando la aplicación se eliminan Cierre las empresas con inversión extranjera. Si la aplicación se cierra correctamente, la siguiente ejecución (cuando estrecha) se borran todos los archivos.

Además, puede iniciar un proceso de fondo para eliminar los archivos que ya no están abiertos. Shellexecute devolver una manija (internamente asociar este mango un nombre de archivo). Este proceso de fondo debe probar el mango del proceso que no existe y Eliminar los archivos asociados.

excusa para la mala Inglés. ; -)

Saludos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top