如何使用 Jersey 通过 Struts 2 框架将文件作为输入流下载?

问题描述 投票:0回答:1

我正在 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]
    
WLTC0017E: Resources rolled back due to setRollbackOnly() being called.
com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E: [Servlet Error]-[ServletNameNotFound]: java.lang.IllegalStateException: Response already committed.

更新:

Struts 2 默默地将文件保存到

temp
文件夹

我发现,如果我使用

File
对象来接受返回的
ByteArrayInputStream
,那么 Struts 2 会以某种方式将文件(正是我正在寻找的)保存到本地
temp
文件夹,而不向用户打开下载对话框。知道怎么挖出来吗?

File fileToDownload = resource.accept(MediaType.APPLICATION_OCTET_STREAM).post(File.class, someXML);

inputStream = new FileInputStream(fileToDownload);
java rest download struts2 inputstream
1个回答
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}
文件名。

© www.soinside.com 2019 - 2024. All rights reserved.