2011-01-07 7 views
41

Napisałem kod generujący plik Excel za pomocą REST JAX-RS i potwierdziłem, że wygenerowany plik Excel znajduje się w katalogu serwera GlassFish.Jak ustawić nagłówek odpowiedzi w JAX-RS, aby użytkownik zobaczył okno pobierania dla programu Excel?

Ale moim celem jest, gdy użytkownik kliknie przycisk (generujący plik Excel .xls), chcę, aby pojawiło się okno pobierania z pytaniem użytkownika, czy zapisać lub otworzyć plik .xls, tak jak inne usługi internetowe, które pobierają typ plików.

Według moich poszukiwań, krok jest:

  1. generować Excel (.xls zrobione)

  2. napisać Excel do strumienia

  3. w pliku JAX-RS, ustaw odpowiedź nagłówek do czegoś podobnego,

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

Moje pytanie brzmi: robię to wszystko w pliku JAX-RS i nie mam dostępnego obiektu HttpServletResponse.

Według odpowiedź od Add Response Header to JAX-RS Webservice

Mówi:

Można wprowadzić odniesienie do rzeczywisty HttpServletResponse poprzez @Context adnotacji w swojej usługa i używać AddHeader() etc , aby dodać nagłówek .

naprawdę nie mogę zrozumieć, co dokładnie to oznacza bez przykładowy kod ..

Odpowiedz

73

Nie potrzebujesz HttpServletResponse, aby ustawić nagłówek odpowiedzi. Możesz to zrobić za pomocą javax.ws.rs.core.Response. Wystarczy dokonać sposób, aby powrócić Response zamiast jednostki:

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

Jeśli nadal chcesz używać HttpServletResponse można dostać to albo wstrzykiwany do jednego z pól klasy, lub za pomocą właściwości lub parametru metody:

@Path("/resource") 
class MyResource { 

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

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

@GarretWilson Dlaczego nie? Co cię myli? To prosty nagłówek. – Tarlog

+0

Ponieważ singleton 'MyResource' miałby funkcję' myMethod() 'wywoływaną przez wiele wątków jednocześnie. Każdy wątek miałby inną instancję 'HttpServletResponse', ale zmienna składowa singleton' anotherServletResponse' może zawierać tylko jedną wartość naraz. Jedyny sposób by to działało, to gdyby 'innyServletResponse' został wstrzyknięty z pewnym proxy bezpiecznym dla wątków, który używa wątku lokalnego lub jakiegoś takiego w celu określenia aktualnej instancji' HttpServletResponse' bieżącego wątku. –

+0

O ile pamiętam, wstrzykiwany jest HttpServletRequestWrapper; jego implementacja pobiera prawdziwy HttpServletRequest z TLS. Więc twoje przypuszczenie jest mniej więcej poprawne. – Tarlog

0

Pomyślałem ustawienie nagłówka odpowiedzi HTTP i strumień, aby wyświetlić download-popup w przeglądarce za pomocą standardowego apletu. uwaga: Używam 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

nie trzeba ustawiać Content-Lenght, jest to jakoś wyliczone na platformie JavaEE ;-) –

Powiązane problemy