Comment télécharger une image sur Google Drive à l'aide de Gapi et réagir


Xim123

J'essaie de télécharger une image sur Google Drive. J'ai suivi ce tutoriel pour télécharger des fichiers, je peux télécharger un fichier simple mais lorsque j'essaye de télécharger une image j'obtiens une image corrompue. En fait, le fichier est téléchargé mais l'image que je veux voir est corrompue. Je sais que le problème est dans le corps de la requête mais je ne sais pas où car c'est une manière étrange (limites, délimiteurs, etc.). Tout fonctionne bien, sauf pour le contenu de l'image, il vous suffit donc de regarder la méthode de publication qui télécharge l'image. Voici mon code:

import { Upload } from 'antd';
import React, { Component } from 'react';

var SCOPE = 'https://www.googleapis.com/auth/drive.file';
var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';


class App extends Component {
  state = {
    name: '',
    googleAuth: '',
    body: ''
  }
  componentDidMount(){
    var script = document.createElement('script');
    script.onload=this.handleClientLoad;
    script.src="https://apis.google.com/js/api.js";
    document.body.appendChild(script);
  }


  initClient = () => {
    try{
      window.gapi.client.init({
          'apiKey': "apikey",
          'clientId': "clientid",
          'scope': SCOPE,
          'discoveryDocs': [discoveryUrl]
        }).then(() => {
          this.setState({
            googleAuth: window.gapi.auth2.getAuthInstance()
          })
          this.state.googleAuth.isSignedIn.listen(this.updateSigninStatus);  
         document.getElementById('signin-btn').addEventListener('click', this.signInFunction);
         document.getElementById('signout-btn').addEventListener('click', this.signOutFunction);

      });
    }catch(e){
      console.log(e);
    }
  }


  signInFunction =()=>{
    console.log(this.state.googleAuth)
    this.state.googleAuth.signIn();
    console.log(this.state.googleAuth)
    this.updateSigninStatus()
  }

  signOutFunction =()=>{
    this.state.googleAuth.signOut();
    this.updateSigninStatus()
  }

  updateSigninStatus = ()=> {
    this.setSigninStatus();
  }

  setSigninStatus= async ()=>{
    console.log(this.state.googleAuth.currentUser.get())
    var user = this.state.googleAuth.currentUser.get();
    console.log(user)
    if (user.wc == null){
      this.setState({
        name: ''
      });
    }
    else{
      var isAuthorized = user.hasGrantedScopes(SCOPE);
      if(isAuthorized){
        console.log('USER')
        console.log(user)
        this.setState({
          name: user.vt.Ad
        });

        const boundary = '-------314159265358979323846';
        const delimiter = "\r\n--" + boundary + "\r\n";
        const close_delim = "\r\n--" + boundary + "--";
        var fileName='mychat123.png';
        var contentType='image/png'
        var metadata = {
          'name': fileName,
          'mimeType': contentType
        };

          var multipartRequestBody =
            delimiter +  'Content-Type: application/json\r\n\r\n' +
            JSON.stringify(metadata) +
            delimiter +
            'Content-Type: ' + contentType + '\r\n';

            multipartRequestBody +=  + '\r\n' + this.state.body;
            multipartRequestBody += close_delim;

          console.log(multipartRequestBody);
          var request = window.gapi.client.request({
            'path': 'https://www.googleapis.com/upload/drive/v3/files',
            'method': 'POST',
            'params': {'uploadType': 'multipart'},
            'headers': {
              'Content-Type': contentType
            },
            'body': multipartRequestBody
          });

        request.execute(function(file) {
          console.log(file)
        });
      }
    }
  }

  getBase64(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result);
      reader.onerror = error => reject(error);
    });
  }
  

  handleChange = async file => {
    let image

    if (file.currentTarget) {
      image = file.currentTarget.currentSrc;
      console.log(file.currentTarget)
    } else {
      if (!file.file.url && !file.file.preview) {
        file.file.preview = await this.getBase64(file.file.originFileObj);
      }
      image = file.file.preview;
      console.log(file.file)
      this.setState({
        body: file.file.preview
      });
    }

    console.log(image)
    
  }

  handleClientLoad = ()=>{
    window.gapi.load('client:auth2', this.initClient);
  }

  render() {
    return (
      <div className="App">
        <Upload 
          style={{width: '100%', height: '200px' }} 
          listType="picture-card" 
          onChange={this.handleChange} >
          <div>
            <div style={{ marginTop: 8 }}>Subir imagen</div>
          </div>
        </Upload>
        <div>UserName: <strong>{ this.state.name}</strong></div>
        <button id="signin-btn">Sign In</button>
        <button id="signout-btn">Sign Out</button>
      </div>
    );
  }
}

export default App;

Pourquoi mon fichier est-il corrompu? Il dit que ce n'est pas un fichier PNG. Quelle est la bonne façon de télécharger une image pour conduire? Merci!!

Tanaike

Points de modification:

  • D'après votre script, il semble que ce this.state.bodysoit les données base64. Dans ce cas, il est nécessaire d'ajouter Content-Transfer-Encoding: base64à l'en-tête des données dans le corps de la demande.
    • Et faites attention aux sauts de ligne du corps de la requête pour multipart/form-data.
  • Lorsque vous souhaitez utiliser uploadType=multipart, veuillez définir multipart/form-data; boundary=###l'en-tête comme type de contenu. Dans votre script, il semble que le type de contenu soit image/png.

Lorsque les points ci-dessus sont reflétés dans votre script, cela devient comme suit.

Script modifié:

De:
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var fileName='mychat123.png';
var contentType='image/png'
var metadata = {
  'name': fileName,
  'mimeType': contentType
};

  var multipartRequestBody =
    delimiter +  'Content-Type: application/json\r\n\r\n' +
    JSON.stringify(metadata) +
    delimiter +
    'Content-Type: ' + contentType + '\r\n';

    multipartRequestBody +=  + '\r\n' + this.state.body;
    multipartRequestBody += close_delim;

  console.log(multipartRequestBody);
  var request = window.gapi.client.request({
    'path': 'https://www.googleapis.com/upload/drive/v3/files',
    'method': 'POST',
    'params': {'uploadType': 'multipart'},
    'headers': {
      'Content-Type': contentType
    },
    'body': multipartRequestBody
  });
À:
const boundary = '-------314159265358979323846';
const delimiter = "--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var fileName = 'mychat123.png';
var contentType = 'image/png';
var metadata = {'name': fileName,'mimeType': contentType};
var multipartRequestBody = delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) + "\r\n" +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n\r\n' +
this.state.body +
close_delim;
console.log(multipartRequestBody);
var request = window.gapi.client.request({
  'path': 'https://www.googleapis.com/upload/drive/v3/files',
  'method': 'POST',
  'params': {'uploadType': 'multipart'},
  'headers': {'Content-Type': 'multipart/form-data; boundary=' + boundary},
  'body': multipartRequestBody
});
  • Dans le téléchargement de l'API Drive, dans l'étape actuelle, il semble que les deux multipart/form-dataet multipart/relatedpeuvent être utilisés.

Remarque:

  • Dans cette réponse, cela suppose que votre jeton d'accès peut être utilisé pour télécharger le fichier sur Google Drive. Veuillez faire attention à cela.

Référence:

Ajoutée:

D'après votre réponse, j'ai remarqué que vous vouliez utiliser à la fetchplace de gapi.client.request. Dans ce cas, l'exemple de script est le suivant.

Ceci est votre script dans votre commentaire.

const fd = new FormData();
fd.append("file", this.state.body);
fd.append("title", 'test.png');
const options = {
  method: 'POST',
  headers: { Authorization: "Bearer" + " " + window.gapi.auth.getToken().access_token },
  body: fd
};
await fetch("googleapis.com/upload/drive/v3/files", options)
.then(response => response.json())
.then(jsonResp => { console.log(jsonResp) });

Points de modification:

  • Dans Drive API v3, la propriété de définition du nom de fichier est name.
  • uploadType=multipart doit être utilisé dans le point de terminaison.
  • Les données base64 doivent être converties en blob.

Lorsque les points ci-dessus sont reflétés dans votre script, cela devient comme suit.

Exemple de script:

// Reference: https://stackoverflow.com/a/16245768
// This method converts from base64 data to blob.
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
  const byteCharacters = atob(b64Data);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  const blob = new Blob(byteArrays, {type: contentType});
  return blob;
}

const metadata = {name: 'test.png'};
const fd = new FormData();
fd.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
fd.append('file', b64toBlob(this.state.body, "image/png"));
fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart', {
  method: 'POST',
  headers: {Authorization: 'Bearer ' + window.gapi.auth.getToken().access_token},
  body: fd
})
.then(response => response.json())
.then(jsonResp => { console.log(jsonResp) });

Articles connexes


Télécharger un fichier sur Google Drive à l'aide de gapi

Robin-Hoodie J'ai suivi cet article ainsi que cette réponse SO sur le téléchargement d'un fichier sur Google Drive qui comprend des métadonnées, ce qui donne le code suivant: readonly BOUNDARY = '--4561564891651634213217'; //Randomly mashed in numbers uploadT

Télécharger l'image sur Google Drive à l'aide de PyDrive

Aldo Suhartono Putra J'ai une question idiote sur PyDrive. J'essaie de créer une API REST en utilisant FastAPI qui téléchargera une image sur Google Drive en utilisant PyDrive. Voici mon code: from fastapi import FastAPI, File from starlette.requests import Re