2013-07-29 13 views
7

Mam aplikację internetową. Używam Java i wiosnę. Aplikacja może utworzyć plik i wysłać go do przeglądarki, to działa poprawnie. Sposób, w jaki to robię, to:Jak usunąć plik po wysłaniu go w aplikacji internetowej?

Tworzę plik w klasie Services, a metoda zwraca adres do kontrolera. Kontroler następnie wysyła plik i jest pobierany poprawnie. Kod dla metody kontrolera jest taki.

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

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

Problemem jest to, że plik jest zapisywany na serwerze, a po wielu wniosków będzie mieć dużo plików. Muszę je usunąć ręcznie. Pytanie brzmi: Jak mogę usunąć ten plik po wysłaniu? lub Czy istnieje sposób wysłania pliku bez zapisania go na serwerze?

Odpowiedz

13

Nie używaj @ResponseBody. Niech Spring wstrzykuje HttpServletResponse i pisze bezpośrednio na jego 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(); 
} 

Nie dodałem żadnych wyjątków. Zostawiam to tobie.

FileSystemResource to po prostu opakowanie po FileInputStream używane przez firmę Spring.

Albo, jeśli chcesz być hardcore, można tworzyć własne FileSystemResource realizacji z własnej getOutputStream() metody zwracającej swoją realizację FileOutputStream że usuwa plik bazowego podczas rozmowy close() na nim.

+0

dzięki. Jak kopiujesz z na zewnątrz? –

+0

Wewnątrz pętli while odczytujesz bajt [] z in i zapisujesz go na zewnątrz. Poszukaj samouczka Java IO. –

+0

Lepiej nie zamykać strumienia wyjściowego odpowiedzi. – rec

2

Postanowiłem więc przyjąć sugestię Sotiriousa na "hardcoreowy" sposób. Jest to dość proste, ale ma jeden problem. Jeśli użytkownik tej klasy otworzy raz strumień wejściowy, aby coś sprawdzić i go zamknąć, nie będzie mógł go ponownie otworzyć, ponieważ plik zostanie usunięty przy zamknięciu. Wiosna nie wydaje się, aby to zrobić, ale trzeba będzie sprawdzić po każdej aktualizacji wersji.

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(); 
     } 
    } 
}