2012-11-30 3 views
8

Ich habe Servlet implementiert, das sich nicht stabil verhält, manchmal mischt es Header im Inhalt und schreibt zweimal dasselbe.Servlet mischt Header und Inhalt und schreibt zweimal dasselbe in der Ausgabe?

und manchmal ist es Datei zurückgibt, die von Inhalt wie folgt gemischt Response-Header enthält:

Server: Apache-Coyote/1.1 
: W/"43-1353687036000" 
DatCCoonntenntt--DDiissppoosittiioonn: : atatatacehnmte;n tf;i lfenlaemnea=m20=12201112211127325421_4W1_Wirnkgi_nSgc_Seern.xnlsx 
sx 
Content-Typ-eT: ype: applaipcatciaoti/on/toctestt-rstare 
am 
ConCtoententy-pTeype: appalicatcion/oon/octet-setarm 
m 
CCoonntent-Lnegtht h: 4199 

Date: te: FriF,r i2,3 2No vNo2v0 120162: 215:25 :G4M2T 
.... 
File content bytes ... 

And again same header and content 

UPDATE * Diese Situation auf tomcat7 geschieht *

Ich habe auch auf getestet Tomcat6 und Jetty, in beiden Fällen gibt es keine Injektion von HTTP-Header zu Response-Inhalt, aber HTTP-Header ist falsch und gibt falschen Dateinamen zurück, der Dateiinhalt ist korrekte Datei. Ich habe bemerkt, dass eine falsche Rückkehr von Servlet passiert, wenn zurückgibt Transfer-Codierung ist chunked.

Wenn ich header stuff, und zweiten Teil der Bytes entfernen, ist es eine gültige Datei. Ist es möglich, dass Synchronisierungsproblem ist?

UPDATE ist hier voll Quelle der Servlet:

public class ExcelDownloadServlet extends HttpServlet 
{ 
    private static final long serialVersionUID = 1L; 
    private static final Logger LOG = Logger 
      .getLogger (ExcelDownloadServlet.class); 


    @Override 
    protected void doGet (HttpServletRequest request, 
      HttpServletResponse response) throws ServletException, IOException 
    { 
     try 
     { 
      TransactionId transactionId = getTransactionId (request); 
      String fileName = 
        request.getParameter (GlobalConstants.EXCEL_FILE); 
      ExcelDownloadType downloadType = 
        ExcelDownloadType 
          .valueOf (request 
            .getParameter (GlobalConstants.EXCEL_DOWNLOAD_TYPE)); 
      ActionContextFactory actionContextFactory = 
        ApplicationContext.getContext() 
          .getActionContextFactory(); 
      //suppress warning. HttpServletRequest.getLocales does not support generics 
      @SuppressWarnings("unchecked") 
      ActionContext actionContext = 
        actionContextFactory.create (request.getSession() 
          .getId(), Collections.<Locale> list (request 
          .getLocales())); 
      GetExcelDataResponse dataResponse = 
        new GetExcelData (transactionId, fileName, downloadType) 
          .execute (actionContext); 
      writeToResponse (response, dataResponse.getFileName(), 
        dataResponse.getData()); 
     } 
     catch (InvalidSessionException e) 
     { 
      LOG.error ("Invalid session in Excel download", e); 
      throw new ServletException (e); 
     } 
     catch (ActionException e) 
     { 
      LOG.error ("Could not download into excel.", e); 
      throw new ServletException (e); 
     } 
    } 

    protected TransactionId getTransactionId (HttpServletRequest request) 
    { 
     return RequestParameterDeserializer.<TransactionId> deserialize (
       request, GlobalConstants.TRANSACTION_ID); 
    } 

    protected void writeToResponse (HttpServletResponse response, 
      String rawFileName, byte[] data) throws IOException 
    { 
     ServletOutputStream sout = null; 
     try 
     {    
      response.setContentType ("application/octet-stream"); 
      response.setContentLength (data.length); 
      // removing blanks from the file name, since FF cuts file names 
      // otherwise. 
      String fileNameWithTime = rawFileName.replaceAll (" ", "_"); 
      response.setHeader ("Content-Disposition", "attachment; filename=" 
        + fileNameWithTime); 
      sout = response.getOutputStream(); 
      sout.write (data, 0, data.length); 
     } 
     finally 
     { 
      if (sout != null) 
      { 
       sout.close(); 
      } 
     } 
    } 

UPDATE * Der Anruf kommt von GWT-Anwendung, wenn sich die URL-Servlet mit den erforderlichen Parametern und setzt in IFrame zu erzeugen, dann Servlet Aufrufe und Datei wird heruntergeladen. Gibt es irgendwelche Vorschläge? *

+2

entfernen Wenn Sie ein Synchronisierungsproblem vermuten würde ich Ihre ganze Servlet empfehlen veröffentlichen, da einige Probleme bei der Synchronisierung von Feldern im Servlet definiert verursacht werden. –

+0

@ kmb385 Ich meine, sollte ich den Teil des Codes synchronisieren, den ich gepostet habe? Es ist sehr einfach Servlet, die angegebene Byte-Array der generierten Datei in der Ausgabe schreibt, und ich bin verwirrend, warum es Antwort Header usw. enthält. –

+0

Da eine neue Instanz einer Antwort und Anfrage für jedes Servlet erstellt werden, sehe ich nicht die Notwendigkeit Synchronisieren Sie diesen Codeblock. Könnten Sie die HTML oder JS, die das Servlet anfordern, posten? –

Antwort

2

Ich hatte ein ähnliches Problem vor langer Zeit. Es stellte sich heraus, dass das Schließen des ServletOutputStream zu einem unerwarteten Verhalten im Anfragefluss führte.

Servlets sollen den Container, der OutputStream zur Verfügung stellt, nicht schließen. Ein anderes Problem könnte manuell die Inhaltslänge festlegen, es ist die Verantwortung des Containers, der den richtigen Wert erzeugt.

Um es zusammenzufassen, versuchen out.close() und response.setContentLength()

+0

Ich habe response.setContentLength() angegeben, ich werde versuchen, out.close() zu entfernen, das Problem tritt selten und schwer zu reproduzieren, danke für die Antwort –