2013-07-29 10 views
7

Ho un'applicazione web. Sto usando java e spring. L'applicazione può creare un file e inviarlo al browser, funziona perfettamente. Il modo in cui lo faccio è:Come eliminare un file dopo averlo inviato in un'app Web?

Creo il file in una classe Servizi e il metodo restituisce l'indirizzo al controller. Il controller invia quindi il file e viene scaricato correttamente. Il codice per il metodo controller è questo.

@RequestMapping("/getFile") 
public @ResponseBody 
FileSystemResource getFile() { 

    String address = Services.createFile(); 
    response.setContentType("application/vnd.ms-excel"); 
    return new FileSystemResource(new File (address)); 
} 

Il problema è che il file viene salvato nel server e dopo molte richieste avrà molti file. Devo cancellarli manualmente. La domanda è: come posso cancellare questo file dopo averlo inviato? o C'è un modo per inviare il file senza salvarlo nel server?

risposta

13

Non utilizzare @ResponseBody. Avere Spring iniettare il HttpServletResponse e scrivere direttamente al suo OutputStream.

@RequestMapping("/getFile") 
public void getFile(HttpServletResponse response) { 
    String address = Services.createFile(); 
    File file = new File(address); 
    response.setContentType("application/vnd.ms-excel"); 
    response.setHeader("Content-disposition", "attachment; filename=" + file.getName()); 

    OutputStream out = response.getOutputStream(); 
    FileInputStream in = new FileInputStream(file); 

    // copy from in to out 
    IOUtils.copy(in,out); 

    out.close(); 
    in.close(); 
    file.delete(); 
} 

Non ho aggiunto alcuna gestione delle eccezioni. Lascio questo a te.

FileSystemResource è davvero solo un wrapper per FileInputStream utilizzato da Spring.

O, se si vuole essere hardcore, si potrebbe fare il vostro proprio FileSystemResource implementazione con un proprio getOutputStream() metodo che restituisce una propria implementazione di FileOutputStream che elimina il file sottostante quando si chiama close() su di esso.

+0

grazie. Come si copia da dentro a fuori? –

+0

All'interno di un ciclo while, si legge un byte [] da dentro e lo si scrive all'esterno. Cerca un tutorial di IO in Java. –

+0

Meglio non chiudere il flusso di output della risposta. – rec

2

Così ho deciso di prendere il suggerimento di Sotirious per un modo "hardcore". È piuttosto semplice, ma ha un problema. Se l'utente di quella classe apre il flusso di input una sola volta per controllare qualcosa e lo chiude, non sarà più in grado di riaprirlo poiché il file viene eliminato alla chiusura. Spring sembra non farlo, ma dovrai controllare dopo ogni aggiornamento della versione.

public class DeleteAfterReadeFileSystemResource extends FileSystemResource { 
    public DeleteAfterReadeFileSystemResource(File file) { 
     super(file); 
    } 

    @Override 
    public InputStream getInputStream() throws IOException { 
     return new DeleteOnCloseFileInputStream(super.getFile()); 
    } 

    private static final class DeleteOnCloseFileInputStream extends FileInputStream { 

     private File file; 
     DeleteOnCloseFileInputStream(File file) throws FileNotFoundException { 
      super(file); 
      this.file = file; 
     } 

     @Override 
     public void close() throws IOException { 
      super.close(); 
      file.delete(); 
     } 
    } 
} 
Problemi correlati