Загрузка файлов больше не работает после обновления до SpringBoot 2.6 и Wicket 9.8

Итак, я обновил приложение с SpringBoot 2.1 до 2.6 и Wicket 8.6 до 9.8, и теперь все работает нормально, кроме загрузки csv-файлов. Я не получаю никакой ошибки, файл создается, как и должен быть, но он не загружается, и я больше не знаю, где искать. Итак, я поделюсь классами кнопки загрузки и самой загрузки. Может быть, у кого-то есть идея.

AjaxФайлСкачать

import java.io.File;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AbstractAjaxBehavior;
import org.apache.wicket.request.IRequestCycle;
import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
import org.apache.wicket.request.resource.ContentDisposition;
import org.apache.wicket.util.file.Files;
import org.apache.wicket.util.resource.FileResourceStream;
import org.apache.wicket.util.resource.IResourceStream;

// Based on: https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
public class AjaxFileDownload extends AbstractAjaxBehavior {
    private static final long serialVersionUID = -3721931990952363001L;

    private File file;
    private boolean deleteAfter;
    private boolean addAntiCache;

    public AjaxFileDownload() {
        this(false, true);
    }

    public AjaxFileDownload(boolean deleteAfter) {
        this(deleteAfter, true);
    }

    public AjaxFileDownload(boolean deleteAfter, boolean addAntiCache) {
        super();
        this.deleteAfter = deleteAfter;
        this.addAntiCache = addAntiCache;
    }

    // Call this method to initiate the download
    public void initiate(AjaxRequestTarget target) {
        if (file == null) {
            throw new IllegalArgumentException("No file has been provided for download.");
        }
        String url = getCallbackUrl().toString();
        if (addAntiCache) {
            url = url + (url.contains("?") ? "&" : "?");
            url = url + "antiCache = " + System.currentTimeMillis();
        }

        // the timeout is needed to let Wicket release the channel
        target.appendJavaScript("setTimeout(\"window.location.href='" + url + "'\", 100);");
    }

    @Override
    public void onRequest() {
        ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(getResourceStream(), getFileName()) {
            @Override
            public void respond(IRequestCycle requestCycle) {
                super.respond(requestCycle);

                if (deleteAfter) {
                    Files.remove(file);
                }
            }
        };
        handler.setContentDisposition(ContentDisposition.ATTACHMENT);
        getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
    }

    private String getFileName() {
        return file.getName();
    }

    private IResourceStream getResourceStream() {
        return new FileResourceStream(new org.apache.wicket.util.file.File(file));
    }

    // Set file to download
    public void setFile(File file) {
        this.file = file;
    }
}

инициация вызывается этим методом

private AbstractButtonPanel createDownloadTemplateButton(String markupId) {
    return new ButtonPanel(markupId) {
        @Override
        protected void buttonClick(final AjaxRequestTarget target) {
            FormExceptionHandler<File> handler = dataHolder -> generateCsvTemplateFile();
            File templateDownload = handler.apply(new WicketExceptionDataholder(target, form, log));

                    fileDownloadBehaviour.setFile(file);
                    fileDownloadBehaviour.initiate(target);
        }

    }.withLinkTextKey("downloadTemplateButton.label");
}

КнопкаПанель

    import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;

public abstract class ButtonPanel extends AbstractButtonPanel {

    public ButtonPanel(String markupId) {
        super(markupId);
    }

    @Override
    protected AjaxLink<Void> createAbstractLink(String markupId) {
        return new AjaxLink<>(markupId) {

            @Override
            public void onClick(AjaxRequestTarget target) {
                buttonClick(target);
            }
        };
    }


    protected abstract void buttonClick(AjaxRequestTarget target);

}

АннотацияКнопка

import com.xyz.uof.frontend.web.bootstrap.css.BootstrapCssEnum;
import com.xyz.uof.frontend.web.bootstrap.css.BootstrapCssEnum.BUTTON;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;


public abstract class AbstractButtonPanel extends Panel {

    /**
     * Change the button to be a link, btn-primary, or what else
     */
    private String buttonSizeClass = BUTTON.SIZE_SMALL;
    private String cssClass = BootstrapCssEnum.BUTTON.PRIMARY;
    private String linkTextKey;
    private String buttonName = "submitButton"; // default
    private IModel<Boolean> visibleModel = Model.of(true);
    private IModel<Boolean> enabledModel = Model.of(true);
    private String iconClass;
    private boolean spinnerActive = false;

    public AbstractButtonPanel(String markupId) {
        super(markupId);
        setOutputMarkupId(true);
    }

    @Override
    protected void onInitialize() {
        super.onInitialize();
        add(createLink("link"));
    }

    @Override
    protected void onConfigure() {
        super.onConfigure();
        setVisibilityAllowed(visibleModel.getObject());
        setEnabled(enabledModel.getObject());
    }

    private AbstractLink createLink(String markupId) {
        AbstractLink ajaxLink = createAbstractLink(markupId);
        ajaxLink.add(new AttributeAppender("class", buttonSizeClass + " " + cssClass, " "));
        ajaxLink.add(createSpinner("spinner", ajaxLink));
        ajaxLink.add(createLabel("label"));
        ajaxLink.add(createIcon("labelIcon"));
        ajaxLink.get("labelIcon").add(new AttributeAppender("class", iconClass, " "));
        return ajaxLink;
    }

    protected abstract AbstractLink createAbstractLink(String markupId);

    private Component createSpinner(String markupId, AbstractLink ajaxLink) {
        if (spinnerActive) {
            ajaxLink.add(new AttributeAppender("onClick", String.format("document.getElementById('%s').childNodes[1].className = 'spinner-grow spinner-grow-sm';", ajaxLink.getMarkupId())));
        }
        return new WebComponent(markupId) {
            @Override
            protected void onConfigure() {
                super.onConfigure();
                getParent().getId();

                setVisibilityAllowed(spinnerActive);
            }
        };
    }
    
    private Label createLabel(String markupId) {
        // Use this model to handle null linkTextKey.
        // Helps to have buttons with glyphicons only
        return new Label(markupId, () -> StringUtils.isNotBlank(linkTextKey) ? getString(linkTextKey) : "") {

            @Override
            protected void onConfigure() {
                super.onConfigure();
                setVisibilityAllowed(StringUtils.isNotBlank(linkTextKey));
            }

        };
    }

    private Component createIcon(String markupId) {
        return new WebComponent(markupId) {
            @Override
            protected void onConfigure() {
                super.onConfigure();
                setVisibilityAllowed(Optional.ofNullable(iconClass).isPresent());
            }
        };
    }

    public AbstractButtonPanel withButtonSizeClass(String buttonSizeClass) {
        this.buttonSizeClass = buttonSizeClass;
        return this;
    }

    public AbstractButtonPanel withCssClass(String cssClass) {
        this.cssClass = cssClass;
        return this;
    }

    // Important for Selenium
    public AbstractButtonPanel withName(String... buttonName) {
        StringBuilder sb = new StringBuilder();
        for (String currentSplit : buttonName) {
            sb.append(currentSplit);
        }
        sb.append(this.buttonName);
        this.buttonName = sb.toString();
        return this;
    }

    public AbstractButtonPanel withLinkTextKey(String linkTextKey) {
        this.linkTextKey = linkTextKey;
        return this;
    }

    public AbstractButtonPanel withVisibleModel(IModel<Boolean> visibleModel) {
        this.visibleModel = visibleModel;
        return this;
    }

    public AbstractButtonPanel withEnabledModel(IModel<Boolean> enabbledModel) {
        this.enabledModel = enabbledModel;
        return this;
    }

    public AbstractButtonPanel withIconName(String iconName) {
        this.iconClass = iconName;
        return this;
    }

    public AbstractButtonPanel withSpinner(boolean spinnerActive) {
        this.spinnerActive = spinnerActive;
        return this;
    }

}

Я не могу сказать, почему ваш код не работает, но вы можете сравнить его с официальными примерами: github.com/apache/wicket/blob/master/wicket-examples/src/mai‌​n/…. С некоторых пор org.apache.wicket.extensions.ajax.AjaxDownloadBehavior является частью модуля wicket-extensions.

martin-g 25.11.2022 09:07
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Итак, проблема была в этой части

    target.appendJavaScript("setTimeout(\"window.location.href='" + url + "'\", 100);");

Javascript был заблокирован, и мне нужно было разблокировать его в другом классе, который расширяет WicketBootSecuredWebApplication, как это

@Override
protected void init() {
super.init();
getCspSettings().blocking().disabled();
}
} 

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