File upload and download in JIRA

Thank you for your visiting.

I use the following code to download a file in the Action class of my custom JIRA plugin.

File file=new File(fileSavePath+"\\"+testFile);         
HttpServletResponse response = ServletActionContext.getResponse();
          response.setHeader("Content-Disposition", "attachment;filename=" + testFile);

          FileInputStream in = new FileInputStream(file);

          OutputStream out = response.getOutputStream(); 
          byte buffer[] = new byte[1024];
          int len = 0;
          while((len=in.read(buffer))>0){
        	  out.write(len);
          }
          in.close();
          out.close();

But exception always occurs,

java.lang.IllegalStateException: response.getWriter() called after response.getOutputStream()
	at com.opensymphony.module.sitemesh.filter.Buffer.getWriter(Buffer.java:72)
	at com.opensymphony.module.sitemesh.filter.PageResponseWrapper$3.activateDestination(PageResponseWrapper.java:100)
	at com.opensymphony.module.sitemesh.filter.RoutablePrintWriter.getDestination(RoutablePrintWriter.java:42)
	at com.opensymphony.module.sitemesh.filter.RoutablePrintWriter.write(RoutablePrintWriter.java:141)
	at com.atlassian.velocity.DefaultVelocityManager.exceptionHandling(DefaultVelocityManager.java:154)
	at com.atlassian.velocity.DefaultVelocityManager.writeEncodedBodyImpl(DefaultVelocityManager.java:123)
	at com.atlassian.velocity.DefaultVelocityManager.writeEncodedBody(DefaultVelocityManager.java:97)
	at com.atlassian.jira.template.velocity.DefaultVelocityTemplatingEngine$DefaultRenderRequest.toWriterImpl(DefaultVelocityTemplatingEngine.java:122)
	at com.atlassian.jira.template.velocity.DefaultVelocityTemplatingEngine$DefaultRenderRequest.asHtml(DefaultVelocityTemplatingEngine.java:113)

does it mean that I should not use method of getOutputStream()?

Thank you.

I dont know what exactly is wrong, but I have a DownloadServlet as well and it works just fine. Take a look


        final FileInputStream inStream = new FileInputStream(tempFile);

        resp.setContentType(mimeType);
        resp.setContentLength((int) tempFile.length());

        resp.setHeader("Content-Disposition", "attachment; filename=" + fileName);

        final OutputStream outStream = resp.getOutputStream();

        final byte[] buffer = new byte[4096];
        int bytesRead = -1;

        while ((bytesRead = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, bytesRead);
        }

        inStream.close();
        outStream.close();

So long

It looks like your action class is invoking the Velocity templating engine, which is obtaining a reference to a Writer.

Can you simply step around the problem by using a servlet instead of an action?

@david.pinn
Yes, the action class invokes a velocity template, maybe it is the reason.
I will change to use the servlet.
Thank you so much.

@M.Abdel-Mola
Thank you so much, it is helpful.

If you’re doing an Action, more than likely your content was getting manipulated by other things in the stack (site mesh comes to mind) which is also trying to write to the response(which you closed). Moving it to the servlet got you out of that mess :slight_smile:

@daniel
Thank you for your explanation.It makes things clear.