YouTube API, Javascript - Загрузить видео - PullRequest
0 голосов
/ 17 марта 2019

Мне нужно загрузить видео на YouTube из моего веб-приложения в Javascript.Я попытался сделать это двумя способами: с помощью их официального API и с помощью CORS.Ни один из них не работал.

Решение 1: с их API

uploadVideo(infos: any, file: File) {
  const params: any = {
    part: 'id,snippet,status',
    media: {
      body: null
    },
    resource: {
      snippet: {
        title: infos.title
      },
      status: {}
    },
    fileSize: file.size
  };
  const fileReader = new FileReader();
  const optSnippetParams = ['description', 'categoryId', 'defaultLanguage'];
  const optStatusParams = ['publishAt', 'privacyStatus', 'license', 'publicStatsViewable'];

  for (const i of optSnippetParams) {
    if (infos[i]) {
      params.resource.snippet[i] = infos[i];
    }
  }

  for (const i of optStatusParams) {
    if (infos[i]) {
      params.resource.status[i] = infos[i];
    }
  }

  if (infos.tags) {
    params.resource.snippet.tags = infos.tags;
  }

  fileReader.onloadend = (e: ProgressEvent) => {
    params.media.body = fileReader.result;

    gapi.client.youtube.videos.insert(params).then((res: any) => {
      console.log(res);
    });
  };

  fileReader.readAsArrayBuffer(file);
}

Это решение не работает, у меня появляется следующая ошибка:

{
  "domain": "youtube.video",
  "location": "body",
  "locationType": "other",
  "message": "The request does not include the video content.",
  "reason": "mediaBodyRequired"
}

Гдевидеоконтент фактически задается в теле запроса.

Решение 2: использование CORS (я вдохновился примером, приведенным в этом файле и этом файле )

uploadVideo(token: string, infos: any, file: File) {
  const body: any = {
    snippet: {
      title: infos.title
    },
    status: {}
  };
  const optSnippetParams = ['description', 'categoryId', 'defaultLanguage'];
  const optStatusParams = ['publishAt', 'privacyStatus', 'license', 'publicStatsViewable'];

  for (const i of optSnippetParams) {
    if (infos[i]) {
      body.snippet[i] = infos[i];
    }
  }

  for (const i of optStatusParams) {
    if (infos[i]) {
      body.status[i] = infos[i];
    }
  }

  if (infos.tags) {
    body.snippet.tags = infos.tags;
  }

  const xhr = new XMLHttpRequest();

  xhr.open('POST', 'https://www.googleapis.com/upload/youtube/v3/videos?part=id,snippet,status', true);
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);

  /**
   * This should works, but doesn't. Error:
   *   {
   *     domain: "global",
   *     message: "Media type 'application/json' is not supported. Valid media types: [video/*, application/octet-stream]"
   *     reason: "badContent"
   *   }
   */
  // xhr.setRequestHeader('Content-Type', 'application/json');

  /** This works */
  xhr.setRequestHeader('Content-Type', file.type);

  /** This works */
  // xhr.setRequestHeader('Content-Type', 'application/octet-stream');

  xhr.setRequestHeader('X-Upload-Content-Length', String(file.size));
  xhr.setRequestHeader('X-Upload-Content-Type', file.type);

  xhr.onload = (e: any) => {
    /** location = null */
    const location = e.target.getResponseHeader('Location');


    /** location is needed to continue upload ... */
  };

  xhr.onerror = (e: any) => {
    console.log('Error:');
    console.log(e);
  };

  xhr.send(JSON.stringify(body));
}

Первое, что в этом коде, это то, что установка 'Content-Type' в 'application/json' не работает.У меня следующая ошибка:

{
  domain: "global",
  message: "Media type 'application/json' is not supported. Valid media types: [video/*, application/octet-stream]"
  reason: "badContent"
}

Однако, это то, что используется здесь в строке 131, поэтому я решил использовать тип файла, который работает.

Во-вторых, мне нужно сделать PUT запрос после POST запроса на успешную загрузку файла.Для этого мне нужно использовать заголовок POST request 'Location'.Однако, когда я пытаюсь получить его, у меня всегда получается null.Поэтому я не могу ничего продолжить.

Какой подход к решению этой проблемы?

...