如何使用Gapi将图像上传到Google驱动器并做出反应 [英] How to upload an image to google drive using gapi and react

查看:59
本文介绍了如何使用Gapi将图像上传到Google驱动器并做出反应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将图像上传到Google驱动器.我按照本教程上传文件,我可以上传一个简单的文件,但是当我尝试上传图像时,我得到了损坏的图像.实际上,文件已上传,但我要查看的图像已损坏.我知道问题出在请求的正文中,但我不知道在哪里,因为这是一种奇怪的方式(边界,定界符等).除了图像的内容之外,其他所有东西都可以正常工作,因此您只需要查看上传图像的post方法即可.这是我的代码:

I'm trying to upload an image to google drive. I followed this tutorial for uploading files, I can upload a simple file but when I try to upload an image I get a corrupted image. In fact, the file is uploaded but the image I want to see is corrupted. I know that the problem is in the body of the request but I don't know where because it's a strange way (boundaries, delimiters, etc). Everything works fine except for the content of the image so you just need to look at the post method that uploads the image. This is my 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;

为什么我的文件损坏了?它说这不是PNG文件.将图片上传到驱动器的正确方法是什么?谢谢!!

Why is my file corrupted? It says that this is not a PNG file. What's the correct way to upload an image to drive? Thank you!!

推荐答案

修改点:

  • 从您的脚本看来, this.state.body 是base64数据.在这种情况下,需要在请求正文中的数据头中添加 Content-Transfer-Encoding:base64 .
    • 并且请注意 multipart/form-data 的请求正文的换行符.
    • Modification points:

      • From your script, it seems that this.state.body is the base64 data. In this case, it is required to add Content-Transfer-Encoding: base64 to the header of data in the request body.
        • And please be careful the line breaks of the request body for multipart/form-data.
        • 当以上几点反映到您的脚本中时,它如下所示.

          When above points are reflected to your script, it becomes as follows.

          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
          });
          

          • 在当前阶段的Drive API上传中,似乎可以同时使用 multipart/form-data multipart/related .
            • 在此答案中,假设您的访问令牌可用于将文件上传到Google云端硬盘.请注意这一点.

            在您的回复中,我注意到您想使用 fetch 而不是 gapi.client.request .在这种情况下,示例脚本如下.

            From your replying, I noticed that you wanted to use fetch instead of gapi.client.request. In this case, the sample script is as follows.

            这是您评论中的脚本.

            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) });
            

            修改点:

            • 在Drive API v3中,用于设置文件名的属性为 name .
            • 必须在终端中使用
            • uploadType = multipart .
            • base64数据需要转换为blob.
              • 为此,我提到了此答案.
              • 当以上几点反映到您的脚本中时,它如下所示.

                When above points are reflected to your script, it becomes as follows.

                // 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) });
                

                这篇关于如何使用Gapi将图像上传到Google驱动器并做出反应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆