Горячий, чтобы использовать Vimeo API для загрузки видео, используя Angular? - PullRequest
0 голосов
/ 17 марта 2020

Я должен подать заявку на загрузку видео в Vimeo. Я получил несколько примеров от друзей прямо здесь, в стеке, но не смог заставить его работать. Вот код, который я собрал у другого разработчика:

vimeo.component. html

<form [formGroup]="vimeoUploadForm">
            <div class="video-inputs">
              <input type="text" placeholder="Vimeo TOKEN key" formControlName="vimeoAPI">
              <input type="text" placeholder="Vimeo Video Name" formControlName="vimeoVideoName">
              <input type="text" placeholder="Vimeo Video Description" formControlName="vimeoVideoDescription">
              <input type="file" (change)="selectFile($event)" multiple #vimeoUpload style="display: none;">
            </div>
          </form>

vimeo.component.ts

import { Component, OnInit } from '@angular/core';

import { FormControl, FormGroup, Validators } from '@angular/forms';
import { VimeoUploadService } from './services/vimeo-upload.service';
import { HttpEventType, HttpResponse } from '@angular/common/http';
import { map, switchMap } from 'rxjs/operators';

@Component({
  selector: 'app-vimeo',
  templateUrl: './vimeo.component.html',
  styleUrls: ['./vimeo.component.scss']
})
export class VimeoComponent implements OnInit {

  public vimeoUploadForm: FormGroup;

  private data: any;
  public uploadPercent;
  // Track upload status by tracking code
  // 0 - Not started
  // 1 - File chosen
  // 2 - Wrong file type
  // 3 - Uploading
  // 4 - Upload error
  // 5 - Upload complete
  public uploadStatus: Number = 0;

  constructor(
    private uploadControl: VimeoUploadService
  ) { }

  selectFile(event): void {
    this.uploadVimeoVideo(event.target.files);
  }

  uploadVimeoVideo(files: FileList): void {
    this.uploadStatus = 1;
    if (files.length === 0) {
      console.log('No file selected!');
      return;
    }
    const file: File = files[0];
    const isAccepted = this.checkAllowedType(file.type);
    if (isAccepted) {
      this.uploadStatus = 1;
      const options = {
        token: this.getFormValue('vimeoAPI'),
        url: 'https://api.vimeo.com/me/videos',
        videoName: this.getFormValue('vimeoVideoName'),
        videoDescription: this.getFormValue('vimeoVideoDescription')
      };
      this.uploadControl.createVimeo(options, file.size)
        .pipe(
          map(data => this.data = data),
          switchMap(
            () => {
              this.uploadControl.updateVimeoLink(this.data.link);
              if (this.data.upload.size === file.size) {
                return this.uploadControl.vimeoUpload(this.data.upload.upload_link, file);
              } else {
                this.uploadStatus = 4;
              }
            }
          )
        ).subscribe(
          event => {
            if (event.type === HttpEventType.UploadProgress) {
              this.uploadPercent = Math.round(100 * event.loaded / event.total);
              this.uploadStatus = 3;
            } else if (event instanceof HttpResponse) {
              this.uploadStatus = 5;
              setTimeout(() => {
                this.uploadStatus = 0;
              }, 5000);
            }
          },
          (error) => {
            console.log('Upload Error:', error);
            this.uploadStatus = 4;
          }, () => {
            console.log('Upload done');
          }
        );
    } else {
      this.uploadStatus = 2;
    }
  }

  initVimeoForm() {
    this.vimeoUploadForm = new FormGroup(
      {
        vimeoAPI: new FormControl('', [Validators.required]),
        vimeoVideoName: new FormControl('', [Validators.required]),
        vimeoVideoDescription: new FormControl('', [Validators.required])
      }
    );
  }

  // HELPERS
  allowUpload(): void {
    this.uploadStatus = 0;
  }

  checkAllowedType(filetype: string): boolean {
    const allowed = ['mov', 'wmv', 'avi', 'flv', 'mp4'];
    const videoType = filetype.split('/').pop();
    return allowed.includes(videoType);
  }

  getFormValue(selector: string) {
    return this.vimeoUploadForm.get(selector).value;
  }

  ngOnInit() {
    // Init Vimeo Data Form
    this.initVimeoForm();
    // Return Vimeo Link from API response
    this.uploadControl.vimeoLinkObs.subscribe(
      data => {
        console.log(data);
      }, error => {
        throw new Error(error);
      }
    );
  }
}

vimeo-upload.service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { HttpClient, HttpEvent, HttpHeaders, HttpParams, HttpRequest } from '@angular/common/http';

@Injectable()
export class VimeoUploadService {

  vimeoObsShare: Observable<string>;
  vimeoResult: string;

  private vimeoLink = new BehaviorSubject('');
  vimeoLinkObs = this.vimeoLink.asObservable();

  constructor(private http: HttpClient) { }

  updateVimeoLink(val) {
    this.vimeoLink.next(val);
  }

  createVimeo(options, fileSize): Observable<any> {
    // CUSTOM HEADERS FOR A FIRST INIT CALL
    const initHeaders = new HttpHeaders(
      {
        'Authorization': 'Bearer ' + options.token,
        'Content-Type': 'application/json',
        'Accept': 'application/vnd.vimeo.*+json;version=3.4'
      }
    );
    // initHeaders.append('Content-Type', 'application/json');
    // initHeaders.append('Accept', 'application/vnd.vimeo.*+json;version=3.4');
    // CUSTOM INIT BODY
    const initBody = {
      'upload': {
        'approach': 'post',
        'size': fileSize
      },
      "privacy": {
        "embed": "private"       // public for public video
      },
      'name': options.videoName,
      'description': options.videoDescription
    };
    if (this.vimeoResult) {
      return new Observable<any>(observer => {
        observer.next(this.vimeoResult);
        observer.complete();
      });
    } else if (this.vimeoObsShare) {
      return this.vimeoObsShare;
    } else {
      return this.http.post(options.url, initBody, { headers: initHeaders });
    }
  }

  vimeoUpload(url, file: File): Observable<HttpEvent<any>> {
    const headers = new HttpHeaders({
      'Tus-Resumable': '1.0.0',
      'Upload-Offset': '0',
      'Content-Type': 'application/offset+octet-stream'
    });
    const params = new HttpParams();
    const options = {
      params: params,
      reportProgress: true,
      headers: headers
    };
    const req = new HttpRequest('PATCH', url, file, options);
    return this.http.request(req);
  }

}

Ошибка, которую я получаю

headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
status: 401
statusText: "Authorization Required"
url: "https://api.vimeo.com/me/videos"
ok: false
name: "HttpErrorResponse"
message: "Http failure response for https://api.vimeo.com/me/videos: 401 Authorization Required"
error:
error: "Unable to upload video. Please get in touch with the app's creator."
link: null
developer_message: "The authentication token is missing a user ID and must be provided when uploading a video."
error_code: 8002

Но я Я использую этот токен: b43db728079bbdf962e84fd41b3b37b2 , который я получил: https://developer.vimeo.com/apps/167964#personal_access_tokens

1 Ответ

2 голосов
/ 17 марта 2020

Прежде всего: никогда не разглашайте свой токен аутентификации в publi c. В зависимости от области действия токена кто-то может использовать его для доступа и изменения вашей учетной записи, загрузки видео в вашу учетную запись и т. Д.

К счастью, это не проблема с токеном в вашем запросе - он имеет только область «publi c» и не может быть использован для загрузки в Vimeo или для доступа к любым частным метаданным. Вы можете проверить область действия токена, отправив запрос на https://api.vimeo.com/oauth/verify с этим токеном ( документы ).

Чтобы загрузить, вам нужно создать новый личный доступ с проверкой подлинности. токен с областями действия public private create edit upload. Оттуда используйте этот токен для аутентификации вашего запроса POST /me/videos ( документы ).

Надеюсь, эта информация поможет!

...