javascript - Hvordan laster jeg programmatisk ned en fil ved å bruke nettleserens innebygde nedlastingswidget i Angular?


Så når jeg ber webtjenesten min om å laste ned en zip-fil, laster den ned filinnholdet hemmelig, og plutselig dukker filen opp i nedlastingslinjen, men allerede fullt nedlastet (100%)

Ved å bruke følgende Angular-metode:

const endpoint = "http://localhost:8080/download/zip"
this.http.get<Blop>(endpoint, {headers: httpHeaders, responseType: 'blob', reportProgress: true })

Så her er hvordan jeg abonnerer:

this.http.get<Blop>(endpoint, {headers: httpHeaders, responseType: 'blob', reportProgress: true }).subscribe({
  next: data => {
    console.log('blocking or not');
    const blob = new Blob([data as any], { type: 'application/zip' });
    window.location.href = URL.createObjectURL(blob);
  }
})

Så jeg la merke til at min console.log(...) ikke blir kalt før slutten av nedlastingen, så jeg antar at nettlesergrensesnittet ikke kan oppdage nedlastingen før det når window.location.href.

Hvordan tvinge nedlastingen til å vises i nedlastingslinjen før overføringen er ferdig, og se nedlastingsfremgangen i nettleseren? Jeg kunne ikke finne noe relatert til asynkron blob eller noe sånt.

PS: min backend leverer en datastrøm, så backenden er ikke problemet. Når jeg kaller API-en min direkte gjennom nettleseren, kan vi se nedlastingsframgangen i nedlastingslinjen. Likevel, hvis dere er interessert, er dette utdraget (spring-boot)

    @GetMapping("/download/zip")
    fun download(response: HttpServletResponse): StreamingResponseBody {
        val file = downloads.download("launcher")

        response.contentType = "application/zip"
        response.setHeader(
            "Content-Disposition",
            "attachment;filename=sample.zip"
        )
        response.setContentLengthLong(file.length())

        return StreamingResponseBody { outputStream: OutputStream ->
            var bytesRead: Int
            val buffer = ByteArray(2048)
            val inputStream: InputStream = file.inputStream()
            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                outputStream.write(buffer, 0, bytesRead)
            }
        }
    }

Svar #1

For nedlasting har du 2 måter:

  1. http.get + msSaveOrOpenBlob (hvis det er definert)/createObjectURL
  • du har full kontroll over forespørsel, prosess og feil. F.eks. kan du avbryte forespørsel, legge til ekstra overskrifter, osv.
  • nedlasting forblir i app-flyt, f.eks. vil F5 avbryte den.
  1. lag skjult nedlastingslink og klikk på den programmessig
  • du kan ikke legge til overskrifter, du kan ikke vise fremgang/feil på en enkel måte (det finnes noen triks som involverer ekstra informasjonskapsler som må settes av backend)
  • Det startes som en separat prosess, f.eks. kan du lukke app-fanen din eller hva som helst.

Det ser ikke ut til å være noen sjanse for å blande disse to tilnærmingene, og generelt vil jeg si at den første er mer moderne og foretrukket for små filer. Men hvis du ikke er fornøyd med den, prøv den andre (https://stackoverflow.com/a/49917066/4019404):

function download(url) {
  const a = document.createElement('a')
  a.href = url
  a.download = url.split('/').pop()
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}

Svar #2

Du kan enkelt bruke denne pakken

npm i ngx-filesaver

og

constructor(private _http: Http, private _FileSaverService: FileSaverService) {
}

onSave() {
  this._http.get('yourfile.png', {
    responseType: ResponseContentType.Blob // This must be a Blob type
  }).subscribe(res => {
    this._FileSaverService.save((<any>res)._body, fileName);
  });
}

fullstendig doc her ngx file saver og også file saver.js

Relaterte artikler