我正在RESTful服务的客户端工作,让用户下载文件。我有权访问服务器端代码。
客户端在Struts 2下并使用一些xml提交POST请求,服务器(在Spring下)将在处理xml后生成zip文件的字节数组表示。我的问题是如何将字节数组转换为一些InputStream
,这是Struts 2下载所需的。
客户端正在使用Struts 2,这是struts.xml
中用于下载文件的配置
<action name="getResponseMessage"
class="DownloadAction"
method="retrieveDownloadableMessage">
<interceptor-ref name="logger" />
<interceptor-ref name="defaultStack" />
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">attachment;filename="${bundleName}"</param>
<param name="bufferSize">1024</param>
</result>
</action>
并且在使用Jersey的java动作类中(对于字段有http状态检查和适当的getter,为简单起见我省略了。):
public class DownloadAction extends ActionSupport {
private InputStream inputStream;
private String bundleName;
public String retrieveDownloadableMessage() throws IOException {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
URI restfulURI = getRestfulURI();
WebResource resource = client.resource(restfulURI);
inputStream = resource.accept(MediaType.APPLICATION_OCTET_STREAM).post(InputStream.class, someXML);
bundleName = "response.zip";
return SUCCESS;
}
}
REST服务器端代码的主干:
@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML })
public Response getPtrXml(Source source) throws IOException {
byte[] myByteArray = generateByteArr(source); // I cannot modify this method.
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(myByteArray);
return Response.ok(byteInputStream, MediaType.APPLICATION_OCTET_STREAM).build();
}
运行客户端代码我在控制台中看到这样的输出。似乎没有任何东西被发送给客户。可能是什么问题呢?
Streaming result [inputStream] type=[application/octet-stream] length=[0] content-disposition=[attachment;filename="${packagePtrName}"] charset=[null]
E WLTC0017E: Resources rolled back due to setRollbackOnly() being called.
E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E: [Servlet Error]-[ServletNameNotFound]: java.lang.IllegalStateException: Response already committed.
更新:Struts 2以静默方式将文件保存到临时文件夹
我发现如果我使用File对象接受返回的ByteArrayInputStream,那么Struts 2会以某种方式将文件(正是我要查找的内容)保存到本地临时文件夹而不向用户打开下载对话框。知道如何挖掘出来吗?
File fileToDownload = resource.accept(MediaType.APPLICATION_OCTET_STREAM).post(File.class, someXML);
inputStream = new FileInputStream(fileToDownload);
答案 0 :(得分:1)
您应该在返回客户端响应之前检查状态代码。由于您没有这样做,因此在读取之前无法返回输入流。
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
您可以从响应中获取输入流
inputStream = response.getEntityInputStream();
if (inputStream != null) {
//read it to make sure the data is available
此外,您没有为bundleName
提供公开的getter,并且您获得了${bundleName}
文件名。