0

I have some issues with Angular's HttpClient:

So, the app logic looks like: component.ts:

I need to call createNewVideoUploadId() from service to get ID for upload video. Than I need to send file to Service Method:

uploadVideoToApi() {
    this.lessonService.createNewVideoUploadId()
        .subscribe(res => {
            this.lessonService.uploadNewVideo(this.videoToUpload, res['X-Upload-File-ID'])
        })
}

lessonService look like:

createNewVideoUploadId() {
    return this.http.get<string>(`${environment.apiUrl}/upload/id`)
}

uploadNewVideo:

uploadNewVideo(video: File, id: string) {

    const chunkSize = 10 * 1024 ** 2;
    const count = Math.ceil(video.size / chunkSize);

    let calls = []

    for (let i = 0; i < count; i++) {
        let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);

        let fd = new FormData();
        fd.append('file', chunk);
        fd.append('file_name', video.name);
        fd.append('file_size', video.size.toString());
        fd.append('chunk_size', chunkSize.toString());
        fd.append('chunk_number', i.toString());
        fd.append('chunks_count', count.toString());

        return this.http.post(`${environment.apiUrl}/upload/${id}`, fd)
    }
} // uploadNewVideo()

So, for loop is stopping in first iteration because of return

I need to execute each for loop iteration one by one from component.ts

So, I need to subscribe to uploadNewVideo, and get responses. But I cant return anything from cycle.

2 Answers 2

1

You could RxJS forkJoin() method. Try the following

uploadNewVideo(video: File, id: string) {
  const chunkSize = 10 * 1024 ** 2;
  const count = Math.ceil(video.size / chunkSize);
  let calls = []

  for (let i = 0; i < count; i++) {
    let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);

    let fd = new FormData();
    fd.append('file', chunk);
    fd.append('file_name', video.name);
    fd.append('file_size', video.size.toString());
    fd.append('chunk_size', chunkSize.toString());
    fd.append('chunk_number', i.toString());
    fd.append('chunks_count', count.toString());

    calls.push(this.http.post(`${environment.apiUrl}/upload/${id}`, fd).pipe(retry(3)))   // <-- retry 3x in case of error
  }

  return forkJoin(calls);     // <-- use `forkJoin` here
}

Now you could subscribe to the function to trigger the calls

uploadVideoToApi() {
  this.lessonService.createNewVideoUploadId().pipe(
    switchMap(res => this.lessonService.uploadNewVideo(this.videoToUpload, res['X-Upload-File-ID'])),
    catchError(error => of(error))
  ).subscribe(
    response => {
      // handle response
    },
    error => {
      // handle error
    }
  );
}
Sign up to request clarification or add additional context in comments.

2 Comments

Yeah, but forkJoin returns each value after for cycle will finish? I need to handle every request and if chunk will lost, resend it.
forkJoin processes each request and will emit value only when all the observables are complete. If you need to resend the request in case of failure, you could pipe in retry operator for each HTTP POST request. You could also use retryWhen if appropriate. I've modified the answer to retry thrice if the POST request fails.
0

Just store the http-post streams in an array and concat thoose:

uploadNewVideo(video: File, id: string) {

    const chunkSize = 10 * 1024 ** 2;
    const count = Math.ceil(video.size / chunkSize);

    let calls = []
    let httpCalls = [];

    for (let i = 0; i < count; i++) {
        let chunk = video.slice(i * chunkSize, (i + 1) * chunkSize);

        let fd = new FormData();
        fd.append('file', chunk);
        fd.append('file_name', video.name);
        fd.append('file_size', video.size.toString());
        fd.append('chunk_size', chunkSize.toString());
        fd.append('chunk_number', i.toString());
        fd.append('chunks_count', count.toString());

        httpCalls.push(this.http.post(`${environment.apiUrl}/upload/${id}`, fd));
    }

    return concat(httpCalls)
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.