如何在Java中使用Undertow返回可下载文件?

3

我正在尝试允许我的游戏客户端下载运行所需的缓存。在我的游戏Web服务器内部,我正在执行以下操作:

@RouteManifest(template="/cache", method="GET")
public class APICacheRoute extends RouteHttpHandler<JadePreprocessor> {
    @Override
    public void handleRequest(HttpServerExchange exchange) throws Exception {
        Path path = Paths.get("./cache/Alterscape.zip");
        File file = path.toFile();
        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/octet-stream");
        exchange.getResponseSender().send(file);
    }
}

然而,我接收到错误提示,该文件必须是ByteBuffer。我如何返回可下载的文件?

我的网络服务器看起来像这样:

public static void initialize() {
    ServerController server = new ServerController("localhost", 8080, 8443);
    server.register(new APIVirtualHost());
    server.inititialize();
}

我的APIVirtualHost如下:

public APIVirtualHost() {
    super(127.0.0.1);
    setDirectoryListingEnabled(false);
}
2个回答

6

使用 Undertow,您需要将处理程序从 I/O 线程中分派出来以使用阻塞操作。每次执行阻塞操作时(例如读取请求正文、接受文件上传流和发送文件),都需要这样做。

在 handle() 方法的顶部,使用此方法将请求分派到一个阻塞线程,并离开非阻塞 I/O 线程:

if (serverExchange.isInIoThread()) {
    serverExchange.dispatch(this);
    return;
}

当准备好发送缓冲区时,请开始阻止:

serverExchange.startBlocking();

然后,要发送一个文件,您可以使用缓冲流:

serverExchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/octet-stream");

final File file = new File("/location/to/your/file");
final OutputStream outputStream = serverExchange.getOutputStream();
final InputStream inputStream = new FileInputStream(file);

byte[] buf = new byte[8192];
int c;
while ((c = inputStream.read(buf, 0, buf.length)) > 0) {
    outputStream.write(buf, 0, c);
    outputStream.flush();
}

outputStream.close();
inputStream.close();
ServerExchange对象上的send方法用于使用非阻塞方法发送响应数据 - 适用于文本或JSON。用于发送原始字节数据的ByteBuffer参数重载, 这是Undertow在发送时将字符串转换为的内容. 这可能会有些误导性。
祝编码愉快。

1
尝试使用io.undertow.server.handlers.BlockingHandler包装自己的处理程序。它已经包含了在执行阻塞操作之前进行必要检查的内容。
public final class BlockingHandler implements HttpHandler {
    ...
    @Override
    public void handleRequest(final HttpServerExchange exchange) throws Exception {

        exchange.startBlocking();
        if (exchange.isInIoThread()) {
            exchange.dispatch(handler);
        } else {
            handler.handleRequest(exchange);
        }
    }
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接