Já tive um problema semelhante, e tive de usar um servlet.
É que o problema é o seguinte: embora pela definição você até pudesse usar um JSP para enviar dados binários (usando response.getOutputStream()), na prática isso não funciona direito (principalmente quando você usa certos produtos como o iPlanet Application Server, um produto da Sun, que foi substituído pelo Sun Java System Application Server). No caso do iPlanet eu recebia uma exceção quando ia pegar response.getOutputStream (isso não ocorria no Tomcat + JBoss).
Se por exemplo você tem de escrever código que funcione em pelo menos duas plataformas diferentes, é mais confiável usar um servlet.
Em um projeto anterior, que não usa Struts, eu uso o JSP para gravar os bytes no cliente, numa boa. Usamos o JBoss/Tomcat aqui.
Agora, no projeto atual eu to usando Struts. Acabei mandando meu Action gravar os bytes via o OutputStream e depois dou um flush e, por fim, dou um “return null;”, ou seja, o Struts não redireciona para nenhuma página posteriormente. Funfa na boa!