2011-01-07 5 views
41

Ho scritto codice che genera file Excel utilizzando REST JAX-RS e ho confermato che il file Excel generato si trova nella directory del server GlassFish.Come impostare l'intestazione della risposta in JAX-RS in modo che l'utente veda il popup di download per Excel?

Ma il mio obiettivo è quando l'utente clicca sul pulsante (che generano Excel .xls), voglio scaricare comparsa per mostrare che chiede all'utente se salvare o aprire il file .xls, proprio come qualsiasi altro servizio web che fa per il download di qualsiasi tipo di file.

Secondo la mia ricerca, il passo è:

  1. generare Excel .xls (FATTO)

  2. scrivere l'excel per lo streaming

  3. nel file di JAX-RS, impostare la risposta intestazione per qualcosa del tipo,

    String fileName = "Blah_Report.xls"; response.setHeader ("Content-Disposition", "attachment; filename =" + fileName);

La mia domanda è che sto facendo tutto questo nel file JAX-RS e non ho l'oggetto HttpServletResponse disponibile.

Secondo la risposta da Add Response Header to JAX-RS Webservice

Egli dice:

si può iniettare un riferimento al reale HttpServletResponse tramite il annotazioni @Context nel webservice e utilizzare AddHeader(), ecc per aggiungere l'intestazione .

Non riesco davvero a capire che cosa esattamente significa senza codice di esempio ..

risposta

73

Non è necessario HttpServletResponse per impostare un'intestazione sulla risposta. Puoi farlo usando javax.ws.rs.core.Response. Basta fare il vostro metodo per restituire risposta invece di entità:

return Response.ok(entity).header("Content-Disposition", "attachment; filename=" + fileName).build() 

Se si desidera continuare a utilizzare HttpServletResponse si può ottenere sia iniettato a uno dei campi di classe, o utilizzando la proprietà, o per parametro del metodo:

@Path("/resource") 
class MyResource { 

    // one way to get HttpServletResponse 
    @Context 
    private HttpServletResponse anotherServletResponse; 

    // another way 
    Response myMethod(@Context HttpServletResponse servletResponse) { 
     // ... code 
    } 
} 
+0

@GarretWilson Perché no? Cosa ti confonde? È un'intestazione semplice. – Tarlog

+0

Poiché un singleton 'MyResource' avrebbe' myMethod() 'chiamato da più thread contemporaneamente. Ogni thread ha una diversa istanza di 'HttpServletResponse', tuttavia la variabile membro singleton' anotherServletResponse' può contenere solo un singolo valore alla volta. L'unico modo in cui ciò funzionerebbe è se "anotherServletResponse' è stato iniettato con un proxy thread-safe che utilizza un thread locale o alcuni di essi per determinare l'effettiva istanza' HttpServletResponse' del thread corrente. –

+0

Per quanto ricordo HttpServletRequestWrapper è stato iniettato; la sua implementazione prende il vero HttpServletRequest dal TLS. Quindi la tua ipotesi è più o meno corretta. – Tarlog

0

ho pensato di impostare un'intestazione di risposta HTTP e streaming per visualizzare download-popup nel browser tramite servlet standard. nota: sto usando Excella, Excel output API.

package local.test.servlet; 

import java.io.IOException; 
import java.net.URL; 
import java.net.URLDecoder; 
import javax.servlet.ServletException; 
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import local.test.jaxrs.ExcellaTestResource; 
import org.apache.poi.ss.usermodel.Workbook; 
import org.bbreak.excella.core.BookData; 
import org.bbreak.excella.core.exception.ExportException; 
import org.bbreak.excella.reports.exporter.ExcelExporter; 
import org.bbreak.excella.reports.exporter.ReportBookExporter; 
import org.bbreak.excella.reports.model.ConvertConfiguration; 
import org.bbreak.excella.reports.model.ReportBook; 
import org.bbreak.excella.reports.model.ReportSheet; 
import org.bbreak.excella.reports.processor.ReportProcessor; 

@WebServlet(name="ExcelServlet", urlPatterns={"/ExcelServlet"}) 
public class ExcelServlet extends HttpServlet { 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 


     try { 

      URL templateFileUrl = ExcellaTestResource.class.getResource("myTemplate.xls"); 
      // /C:/Users/m-hugohugo/Documents/NetBeansProjects/KogaAlpha/build/web/WEB-INF/classes/local/test/jaxrs/myTemplate.xls 
      System.out.println(templateFileUrl.getPath()); 
      String templateFilePath = URLDecoder.decode(templateFileUrl.getPath(), "UTF-8"); 
      String outputFileDir = "MasatoExcelHorizontalOutput"; 

      ReportProcessor reportProcessor = new ReportProcessor(); 
      ReportBook outputBook = new ReportBook(templateFilePath, outputFileDir, ExcelExporter.FORMAT_TYPE); 

      ReportSheet outputSheet = new ReportSheet("MySheet"); 
      outputBook.addReportSheet(outputSheet); 

      reportProcessor.addReportBookExporter(new OutputStreamExporter(response)); 
      System.out.println("wtf???"); 
      reportProcessor.process(outputBook); 


      System.out.println("done!!"); 
     } 
     catch(Exception e) { 
      System.out.println(e); 
     } 

    } //end doGet() 

    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 

    } 

}//end class 



class OutputStreamExporter extends ReportBookExporter { 

    private HttpServletResponse response; 

    public OutputStreamExporter(HttpServletResponse response) { 
     this.response = response; 
    } 

    @Override 
    public String getExtention() { 
     return null; 
    } 

    @Override 
    public String getFormatType() { 
     return ExcelExporter.FORMAT_TYPE; 
    } 

    @Override 
    public void output(Workbook book, BookData bookdata, ConvertConfiguration configuration) throws ExportException { 

     System.out.println(book.getFirstVisibleTab()); 
     System.out.println(book.getSheetName(0)); 

     //TODO write to stream 
     try { 
      response.setContentType("application/vnd.ms-excel"); 
      response.setHeader("Content-Disposition", "attachment; filename=masatoExample.xls"); 
      book.write(response.getOutputStream()); 
      response.getOutputStream().close(); 
      System.out.println("booya!!"); 
     } 
     catch(Exception e) { 
      System.out.println(e); 
     } 
    } 
}//end class 
14
@Context ServletContext ctx; 
@Context private HttpServletResponse response; 

@GET 
@Produces(MediaType.APPLICATION_OCTET_STREAM) 
@Path("/download/{filename}") 
public StreamingOutput download(@PathParam("filename") String fileName) throws Exception { 
    final File file = new File(ctx.getInitParameter("file_save_directory") + "/", fileName); 
    response.setHeader("Content-Length", String.valueOf(file.length())); 
    response.setHeader("Content-Disposition", "attachment; filename=\""+ file.getName() + "\""); 
    return new StreamingOutput() { 
     @Override 
     public void write(OutputStream output) throws IOException, 
       WebApplicationException { 
      Utils.writeBuffer(new BufferedInputStream(new FileInputStream(file)), new BufferedOutputStream(output)); 
     } 
    }; 
} 
+0

non è necessario impostare Content-Lenght, è in qualche modo calcolato nella piattaforma JavaEE ;-) –