Как отправить перенаправление после загрузки файла в сервлете

Я разрабатываю веб-страницу, используя Java сервлеты и JSP. У меня есть функционал, где в зависимости от полученного действия (действия) выполняются разные операции. Однако я столкнулся с проблемой с определенным действием (действие4), которое должно создать PDF-файл, а затем перенаправить пользователя на другую страницу.

Вопросы:

  • Как я могу правильно перенаправить на страницу после создания PDF-файла?
  • Есть ли способ завершить загрузку PDF-файла, а затем выполнить перенаправление?

Я ценю любую помощь или предложения, которые вы можете предложить. Заранее спасибо!

Ниже приведена моя структура и проблема, с которой я столкнулся.

Сервлет:

if (action != null) {
    switch (action) {
        case "action1": // Add items to cart
            if (carritoSQL.existeProducto(producto)) {
                handleAddButton(request, response, producto, cantidad, carrito);
            }
            break;
        case "action2": // Development-focused case
            handleClearButton(request, response, session);
            break;
        case "action3": // Cancel purchase
            handleClearButton(request, response, session);
            redirect = "views/home.jsp";
            break;
        case "action4": // Complete purchase
            handleCompletePurchaseButton(request, response, fecha, vendedor, distribuidor, carrito);
            handleClearButton(request, response, session);
            request.getRequestDispatcher("views/home.jsp").forward(request, response);
            //redirect = "views/home.jsp";
            break;
        default:
            // Default logic if necessary
            defaultHandler(request, response);
            redirect = "views/home.jsp";
            break;
    }
} else {
    // Handle the case where no 'action' value is received
    defaultHandler(request, response);
}

response.sendRedirect(redirect);

private void handleCompletePurchaseButton(HttpServletRequest request, HttpServletResponse response, String fecha, String vendedor, String distribuidor, ShoppingCart carrito) throws ServletException, IOException {
    GeneralReceipt receipt = createReceipt(fecha, vendedor, distribuidor, carrito);
    detailReceipt(receipt.getId(), fecha, vendedor, distribuidor, carrito);
    String ticket = generateTicketString(vendedor, distribuidor, carrito, receipt);
    generatePDF(response, ticket, distribuidor, fecha);
}

Проблема: Проблема возникает с действием4. В результате операции корректно генерируется PDF-файл, который затем загружается пользователем, но перенаправления на страницу не происходит. Я попробовал следующие решения:

  • response.sendRedirect("views/home.jsp");
  • request.getRequestDispatcher("views/home.jsp").forward(запрос, ответ);

Оба решения приводят к следующей ошибке в консоли:

28-Jun-2024 10:50:29.355 SEVERE [68] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [operacionesRemisionNH1] threw exception
    java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
        at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:486)
        at Servlets.operacionesRemisionNH1.generatePDF(operacionesRemisionNH1.java:354)
        at Servlets.operacionesRemisionNH1.handleCompletePurchaseButton(operacionesRemisionNH1.java:153)
        at Servlets.operacionesRemisionNH1.doPost(operacionesRemisionNH1.java:114)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:232)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)

JSP, где я вызываю action4:

<div class = "modal fade" id = "FinalizarCompraModal" tabindex = "-1" aria-labelledby = "FinalizarCompraModalLabel" aria-hidden = "true">
    <div class = "modal-dialog modal-dialog-centered">
        <div class = "modal-content">
            <div class = "modal-header">
                <h5 class = "modal-title" id = "FinalizarCompraModalLabel">Purchase Confirmation</h5>
                <button type = "button" class = "btn-close" data-bs-dismiss = "modal" aria-label = "Close"></button>
            </div>
            <div class = "modal-body">
                You are about to complete your purchase. Please review your order details. If everything is correct, click 'Confirm' to complete the purchase. If you need to make any changes, click 'Cancel'.
            </div>
            <div class = "modal-footer">
                <button type = "button" class = "btn btn-secondary" data-bs-dismiss = "modal">Cancel</button>
                <button type = "submit" name = "action" value = "action4" class = "btn btn-primary">Confirm</button>
            </div>
        </div>
    </div>
</div>

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Действительно, вы не можете отправить несколько ответов на один запрос. По сути, после этого вам нужно запустить второй запрос.

Лучше всего добавить определенный файл cookie в ответ, представляющий загрузку файла, и опросить его в JavaScript, а затем выполнить перенаправление в JavaScript, когда файл cookie будет найден.

По сути, в сервлете:

response.setHeader("Content-Disposition", ...);
response.addCookie(new Cookie("download.completed", "true"));
// now write to response.getOutputStream()

А в JSP дайте кнопке загрузки идентификатор, чтобы мы могли ссылаться на нее в JS:

<button type = "submit" id = "yourDownloadButton" ...>

И запустите этот JS, когда контент DOM будет готов, чтобы при нажатии кнопки загрузки запускался опрос файлов cookie. Когда файл cookie будет найден, в этом примере будет показано предупреждение (конечно, в демонстрационных целях вы можете безопасно удалить его), а затем перенаправление на ваш текущий вопрос:

document.getElementById("yourDownloadButton").addEventListener("click", () => {
    document.cookie = "download.completed=false";
    const downloadCompleteChecker = setInterval(() => {
        if (document.cookie.includes("download.completed=true")) {
            clearInterval(downloadCompleteChecker);
            alert("Download completed!");
            window.location = "https://stackoverflow.com/q/78683578";
        }
    }, 500);
});

Огромное спасибо за подробное объяснение и решение! Я реализовал предложенный подход, используя файл cookie, сигнализирующий о завершении загрузки, и функцию JavaScript для обработки перенаправления. Это сработало отлично

Carlos Odette DLCL 28.06.2024 21:10

Другие вопросы по теме