2

I want to download large file. Current solution works fine but user can't see progress in browser's download manager window and I have to handle progress by myself (only by displaying infinite progress indicator). Is it possible somehow to stream data instead of downloading them first to local temporary PC and invoking "download" action on already downloaded file?

Something like you normally download some large file (windows ISO, ...) and you see instant download progress.

My server is writter like this:

        ExportedData exportedData = this.taxExportService.resolveExportedData(taskId);
        CoreTaskQueueDto coreTaskQueueDto = exportedData.taskQueueDto();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy__HH_mm_ss")
                .withZone(zoneId)
                .withLocale(locale);
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setContentLength((int) exportedData.size());
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment()
                .filename("%s-%s.zip".formatted(coreTaskQueueDto.getType(), formatter.format(coreTaskQueueDto.getCreated())), StandardCharsets.UTF_8)
                .build()
                .toString());
        try {
            IOUtils.copy(exportedData.inputStream(), response.getOutputStream());
            response.flushBuffer();
        } catch (IOException e) {
            throw new CoreException(e);
        } finally {
            try {
                exportedData.inputStream().close();
            } catch (IOException e) {
                log.warn("Error closing download stream.", e);
            }
        }

My AXIOS client is written like this:

    const response: AxiosResponse<Blob> = await taxGuruAxios.get(url, {
        responseType: "blob",
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        noErrorToast,
    });

and then

    const blob = response.data;
    const blobUrl = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = blobUrl;
    a.download = parseFileNameFromContentDisposition(response) ?? "unknown-file-name-and-type";
    a.click();
    a.remove();
    window.URL.revokeObjectURL(blobUrl);

I have not tried any other solution.

Adam Ostrožlík
  • 1,256
  • 1
  • 10
  • 16

1 Answers1

0

Looks like I resolved this problem by just ignoring axios completely.

    const a = document.createElement("a");
    a.href = axiosInstance.getUri({url: "here goes target URI"});
    a.click();
    a.remove();

I think I am lucky I did not have to handle authentication problem since I am using cookies which are sent automatically with download request.

Adam Ostrožlík
  • 1,256
  • 1
  • 10
  • 16