当前位置: 首页 > 知识库问答 >
问题:

如何完全中止输出流下载?

沈英勋
2023-03-14

我们目前正在开发一项服务,该服务将归档数据并将其作为ZipoutStream返回用户。我们目前正在寻找的是,如果服务器端出现问题,可以完全终止操作。在我们当前的实现中(仅关闭响应输出流),错误会导致用户端出现格式错误的zip,但在尝试解压之前,无法告知归档文件是否格式错误。期望的行为类似于下载终止(例如,从浏览器的角度来看,它会导致不成功的下载指示(红十字图标或类似的东西,取决于浏览器)明确地告诉用户出了问题)。我们使用的是Spring Boot,因此任何java代码示例都非常受欢迎,但是如果您知道负责这种行为的底层HTTP机制,并且能够指向正确的方向,那么您也会非常受欢迎。以下是我们目前的情况(输出是SpringREST控制器的响应输出流(HttpServletResponse.getOutputStream()):

try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) {
        try {
            for (ZipRecordFile fileInfo : zipRecord.listZipFileOverride()) {
                InputStream fileStream = getFileStream(fileInfo.s3region(), fileInfo.s3bucket(),
                    fileInfo.s3key());
                ZipEntry zipEntry = new ZipEntry(fileInfo.fileName());
                zipOutputStream.putNextEntry(zipEntry);
                fileStream.transferTo(zipOutputStream);
            }
        }
        catch (Exception e) {
            outputStream.close();
        }
    }

共有2个答案

微生慈
2023-03-14

我认为你应该抛出异常而不是处理它。

用你的捕捉块,你正在处理异常。

    catch (Exception e) {
        outputStream.close();
    }

此外,由于您的代码正在使用try-with-Resources块,您不应该需要另一个try块,也不需要显式关闭zipOutputStream

赵夕
2023-03-14

没有一种(干净的)方法来做你想做的事:

一旦开始将ZIP文件写入输出流,更改HTTP响应代码就太晚了。响应代码在响应开始时发送。

因此,HTTP服务器没有正确的方法告诉HTTP客户端:“嘿...忽略我发给你的ZIP文件,因为它已经损坏了”。

那么,还有什么选择呢?

>

  • 在服务器端,将整个ZIP创建为内存中的对象或将其写入临时文件。如果成功,则发送2xx响应,后跟ZIP数据。如果失败,请发送4xx或5xx响应。

    主要的问题是您需要足够的内存或文件系统空间来保存ZIP文件。

    重新设计HTTP API,以便客户端可以发送第二个请求,以检查第一个请求的响应是否包含完整的ZIP文件。

    您也许能够利用MIME多部分编码。一个良好形成的MIME多部分的每个部分都有一个开始标记和一个结束标记。你可以尝试让你的网络应用“手工”构建包含ZIP的多部分流。如果它决定必须中止ZIP,它可以只关闭输出流而不添加所需的结束标记。

    这样做的主要问题是,您依赖客户端的HTTP堆栈来告诉浏览器(或其他任何东西)多部分已损坏。此外,浏览器(或其他)不得将部分(即损坏的)ZIP文件传递给用户。我不确定你是否可以依靠(特定的)网络浏览器来做到这一点。

    如果您在客户端通过自定义代码运行下载,那么您可以实现自己的封装协议。效果将与3相同。。。但你不会滥用MIME规范。

  •  类似资料:
    • 嗨,我有一个maven项目,需要在集成测试开始之前将2个WAR部署到一个jetty环境中。在正常情况下,这些WAR不是项目的依赖项,但它们需要分开部署,以便集成测试发挥作用。 有人知道如何在只下载依赖项而不做任何更多事情的war上添加依赖项吗?

    • 我们正在尝试让一个iOS的应用程序被批准进入AppStore。我们正在我们的应用程序中利用Spotify API的一部分,因此正在使用Spotify网络授权流。 在Spotify提供的登录页面上,它显示了“注册”链接和登录链接。苹果不喜欢这样,因为它违反了“准则3.1.1 -应用内商业支付购买”,因为我们在我们的应用内推广其他应用。我们发现添加< code>nosignup和< code>noli

    • 我使用的是——保留类和——保留类成员,但这些似乎只保留类中的方法名称和字段,我想告诉Proproaurd不要碰特定方法内部的任何东西,即使是“for”循环或“if”语句,甚至变量名称!,我想看到一个方法在反编译后看起来与原始版本完全相同,就像您在调试模式下反编译程序时一样!,但只有一种方法而不是所有其他方法。 有没有办法使用proGuard做到这一点? 谢谢:)

    • 问题内容: 我想制作一个Servlet过滤器,该过滤器将在处理和完成响应后读取响应的内容,并以XML或PDF或其他方式返回该信息。但是我不确定如何从HttpServletResponse对象中获取任何信息。我如何获得此信息? 问题答案: 将此添加到过滤器java文件。 使用以下代码: 现在,content变量具有输出流。您也可以对二进制内容执行此操作。

    • 只是想知道在我完成输入后如何终止程序?因为在几次“输入”之后扫描仪仍然会继续,假设我要继续输入...我试过了: 和 它们不起作用....程序继续运行,打乱了初衷,

    • 现在我在我的程序中所做的是,我使用和使它全屏运行,显示看起来非常好,但问题是在我的屏幕的左侧和右侧都有图像(边框),而且还有一个蓝色背景。在改变屏幕和分辨率时,这些会受到干扰,并且不能正确显示。那些灰色的补丁又出现了 我有一个Java程序,我想总是在全屏打开;我无法找到一种方法来正确地做它,所以我把最小值调整为(1370,727)和最大值。因此,它开始在我的笔记本电脑上正常打开,但当我把笔记本电脑