Search code examples
javaspringrestdownloadgwtp

GWTP and Spring REST file download


I'm working on a project where i have download a file generated in the server, I'm using Spring in the server :

@RestController
@RequestMapping(value = ApiPaths.FORM)
public class ExportController {
Log log = LogFactory.getLog(getClass());
@Autowired
DataExportService dataExportService;

@RequestMapping(method = GET, value = PathParameter.ID, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody public HttpEntity<byte[]> getFile(@PathVariable(RestParameter.ID) Long id) {
    FileSystemResource file = null;
    try {
        file = dataExportService.exportData("file", id);
        if (file.exists()) {
            byte[] bytes = IOUtils.toByteArray(file.getInputStream());
            HttpHeaders header = new HttpHeaders();
            header.set("Content-Disposition", "attachment; filename=" + file.getFilename());
            header.setContentLength(file.getFile().length());
            return new HttpEntity<>(bytes, header);
        }
    } catch (IOException e) {
        log.info(e.getMessage());
        e.printStackTrace();
    }
    return new HttpEntity<>(null, new HttpHeaders());
}

}

the file is generated just fine, but on the client side i can't figure out how to continue, i tried this:

i have this service:

@Path(ApiPaths.FORM)
public interface ExportFormService {
     @GET
     @Path(PathParameter.ID)
     RestAction<byte[]> exportformById(@PathParam(RestParameter.ID) Long id);
}

wich i use in the presenter of a widget (on click of a button):

public class DynamicFormsPresenter extends Presenter<MyView, MyProxy> implements DynamicFormsUiHandlers,
        FormSavedEvent.FormSavedHandler {

    @ProxyStandard
    @NameToken({NameTokens.FORM, NameTokens.FORM_DETAILS})
    public interface MyProxy extends ProxyPlace<DynamicFormsPresenter> {
    }

    public interface MyView extends View, HasUiHandlers<DynamicFormsUiHandlers> {
        ...
    }

    public static final Object FORM_BUILDER = new Object();

    private final PlaceManager placeManager;
    private final RestDispatch dispatcher;
    private final PlaceRequest placeRequest;
    private final ExportFormService exportFormService;
    private final FormBuilderPresenterFactory formBuilderPresenterFactory;

    @Inject
    DynamicFormsPresenter(EventBus eventBus,
                          MyView view,
                          MyProxy proxy,
                          PlaceManager placeManager,
                          RestDispatch dispatcher,
                          PlaceRequest placeRequest,
                          DynamicFormService dynamicFormService,
                          ExportFormService exportFormService,
                          FormBuilderPresenterFactory formBuilderPresenterFactory) {
        super(eventBus, view, proxy, EntryPresenter.SLOT_ENTRY);

        this.placeManager = placeManager;
        this.dispatcher = dispatcher;
        this.placeRequest = placeRequest;
        this.exportFormService = exportFormService;
        this.formBuilderPresenterFactory = formBuilderPresenterFactory;

    }

    ....

    @Override
    public void exportForm(DynamicFormVO dynamicFormVO) {
        dispatcher.execute(exportFormService.exportformById(dynamicFormVO.getId()),
                new AbstractAsyncCallback<byte[]>() {
                    @Override
                    public void onReceive(byte[] response) {
                    }
                });
    }

    ....
}

I don't know what to do next,

INFO: I also tried this solution, but it didn't work (nothing happened).


Solution

  • You shouldn't use GWTP's REST Dispatch for a file download. Simply add a Frame in your View

    <g:Frame ui:field="downloadFrame" height="0" width="0" visible="false"/>
    

    Then set the URL of the frame to the path your Spring handler :

    UrlBuilder builder = new UrlBuilder()
                .setProtocol(Window.Location.getProtocol())
                .setHost(Window.Location.getHost())
                .setPath(ApiPaths.FORM + id);
    downloadFrame.setUrl(builder.build());