简体   繁体   English

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

[英]How to return a file to download in Java using Undertow?

I am trying to allow my game client to download the cache needed for the client to run.我试图让我的游戏客户端下载客户端运行所需的缓存。 Inside of my game web server I am doing this:在我的游戏网络服务器内部,我正在这样做:

@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);
    }
}

However, I am receiving the error that the file must be a ByteBuffer.但是,我收到文件必须是 ByteBuffer 的错误。 How can I return a file to download?如何返回要下载的文件?

My web server looks like this:我的网络服务器看起来像这样:

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

My APIVirtualHost looks like this:我的 APIVirtualHost 看起来像这样:

public APIVirtualHost() {
    super(127.0.0.1);
    setDirectoryListingEnabled(false);
}

With Undertow, you need to dispatch the handler off the I/O thread to use a blocking operation.使用 Undertow,您需要从 I/O 线程分派处理程序以使用阻塞操作。 You'll need to do this any time you need to perform blocking operations, such as reading the a request body, accepting a file upload stream, and of course, sending a file.您需要在需要执行阻塞操作时执行此操作,例如读取请求正文、接受文件上传流,当然还有发送文件。

At the top of your handle() method, use this to dispatch the request to a blocking thread, and off the non-blocking I/O thread:在 handle() 方法的顶部,使用它来将请求分派到阻塞线程,并关闭非阻塞 I/O 线程:

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

Then start blocking when you're ready to send the buffer:然后在您准备好发送缓冲区时开始阻塞:

serverExchange.startBlocking();

Then to send a file, you can use a Buffered stream:然后要发送文件,您可以使用缓冲流:

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();

The send method on the ServerExchange object is for sending response data using the non-blocking method - good for text or JSON. ServerExchange对象上的send方法用于使用非阻塞方法发送响应数据 - 适用于文本或 JSON。 The ByteBuffer argument overload is for sending raw byte data, which is what Undertow converts strings to when sending. ByteBuffer参数重载用于发送原始字节数据,这是 Undertow 在发送时将字符串转换为的内容。 It can be a bit misleading.这可能有点误导。

Happy Coding.快乐编码。

Try to wrap your own handler with this io.undertow.server.handlers.BlockingHandler .尝试用这个io.undertow.server.handlers.BlockingHandler包装你自己的处理程序。 It already contains the necessary checks before performing a blocking operation.在执行阻塞操作之前,它已经包含了必要的检查。

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);
        }
    }
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM