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

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

问题描述

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

import { Upload } from 'antd';从'react'导入反应,{组件};var SCOPE = 'https://www.googleapis.com/auth/drive.file';var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';类应用扩展组件{状态 = {名称: '',谷歌验证:'',身体: ''}组件DidMount(){var script = document.createElement('script');script.onload=this.handleClientLoad;script.src=https://apis.google.com/js/api.js";document.body.appendChild(脚本);}initClient = () =>{尝试{window.gapi.client.init({'apiKey':apikey",'clientId': 'clientid',范围":范围,'discoveryDocs':[discoveryUrl]}).then(() => {这个.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);});}捕捉(e){控制台.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=异步()=>{console.log(this.state.googleAuth.currentUser.get())var user = this.state.googleAuth.currentUser.get();控制台日志(用户)如果(user.wc == null){这个.setState({名称: ''});}别的{var isAuthorized = user.hasGrantedScopes(SCOPE);如果(已授权){console.log('用户')控制台日志(用户)这个.setState({名称:user.vt.Ad});常量边界='-------314159265358979323846';const delimiter = "
--";+ 边界 + "
";const close_delim = "
--";+ 边界 + --";var fileName='mychat123.png';var contentType='图片/png'变量元数据 = {名称":文件名,'mimeType':内容类型};var multipartRequestBody =delimiter + 'Content-Type: application/json

' +JSON.stringify(元数据) +分隔符 +'内容类型:' + contentType + '
';multipartRequestBody += + '
' + this.state.body;multipartRequestBody += close_delim;console.log(multipartRequestBody);var request = window.gapi.client.request({'路径': 'https://www.googleapis.com/upload/drive/v3/files','方法':'POST','params': {'uploadType': 'multipart'},标题":{内容类型":内容类型},正文":多部分请求正文});request.execute(函数(文件){控制台日志(文件)});}}}getBase64(文件){return new Promise((resolve, reject) => {const reader = new FileReader();reader.readAsDataURL(文件);reader.onload = () =>解决(读者.结果);reader.onerror = 错误 =>拒绝(错误);});}handleChange = 异步文件 =>{让图像如果(file.currentTarget){图像 = 文件.currentTarget.currentSrc;console.log(file.currentTarget)} 别的 {if (!file.file.url && !file.file.preview) {file.file.preview = 等待 this.getBase64(file.file.originFileObj);}图像 = 文件.文件.预览;控制台.log(文件.文件)这个.setState({正文:file.file.preview});}控制台日志(图像)}处理客户端负载 = ()=>{window.gapi.load('client:auth2', this.initClient);}使成为() {返回 (<div className="App"><上传样式={{宽度:'100%',高度:'200px'}}listType="图片卡";onChange={this.handleChange} >

<div style={{ marginTop: 8 }}>Subir imagen</div></div></上传><div>用户名:<strong>{ this.state.name}</strong></div><button id="signin-btn">登录</button><button id="signout-btn">退出</button></div>);}}导出默认应用程序;

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

解决方案

修改点:

  • 从您的脚本看来,this.state.body 是 base64 数据.在这种情况下,需要在请求体的数据头部添加Content-Transfer-Encoding: base64.
    • 请注意 multipart/form-data 的请求正文的换行符.
  • 当您要使用uploadType=multipart时,请设置multipart/form-data;boundary=### 到标题作为内容类型.在您的脚本中,内容类型似乎是 image/png.

当以上几点反映到你的脚本中时,它变成如下.

修改脚本:

从:

const 边界 = '-------314159265358979323846';const delimiter = "
--";+ 边界 + "
";const close_delim = "
--";+ 边界 + --";var fileName='mychat123.png';var contentType='图片/png'变量元数据 = {名称":文件名,'mimeType':内容类型};var multipartRequestBody =delimiter + 'Content-Type: application/json

' +JSON.stringify(元数据) +分隔符 +'内容类型:' + contentType + '
';multipartRequestBody += + '
' + this.state.body;multipartRequestBody += close_delim;console.log(multipartRequestBody);var request = window.gapi.client.request({'路径': 'https://www.googleapis.com/upload/drive/v3/files','方法':'POST','params': {'uploadType': 'multipart'},标题":{内容类型":内容类型},正文":多部分请求正文});

到:

const 边界 = '-------314159265358979323846';const delimiter = "--";+ 边界 + "
";const close_delim = "
--";+ 边界 + --";var fileName = 'mychat123.png';var contentType = '图片/png';var metadata = {'name': fileName,'mimeType': contentType};var multipartRequestBody = 分隔符 +'内容类型:应用程序/json

' +JSON.stringify(元数据) + "
"+分隔符 +'内容类型:' + contentType + '
' +'内容传输编码:base64

' +这个.state.body +close_delim;console.log(multipartRequestBody);var request = window.gapi.client.request({'路径': 'https://www.googleapis.com/upload/drive/v3/files','方法':'POST','params': {'uploadType': 'multipart'},'headers': {'Content-Type': 'multipart/form-data;边界='+边界},正文":多部分请求正文});

  • Drive API的上传,现阶段,multipart/form-datamultipart/related似乎都可以使用.

注意:

  • 在此答案中,它假设您的访问令牌可用于将文件上传到 Google 云端硬盘.请注意这一点.

参考:

补充:

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

这是您评论中的脚本.

const fd = new FormData();fd.append(文件", this.state.body);fd.append("title", 'test.png');常量选项 = {方法:'POST',标头:{授权:承载";+""+ window.gapi.auth.getToken().access_token },身体:fd};等待获取(googleapis.com/upload/drive/v3/files",选项).then(response => response.json()).then(jsonResp => { console.log(jsonResp) });

修改点:

  • 在 Drive API v3 中,用于设置文件名的属性是 name.
  • uploadType=multipart 必须在端点中使用.
  • 需要将 base64 数据转换为 blob.

当以上几点反映到你的脚本中时,它变成如下.

示例脚本:

//参考:https://stackoverflow.com/a/16245768//此方法将 base64 数据转换为 blob.常量 b64toBlob = (b64Data, contentType='', sliceSize=512) =>{const byteCharacters = atob(b64Data);常量字节数组 = [];for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {常量 slice = byteCharacters.slice(offset, offset + sliceSize);const byteNumbers = new Array(slice.length);for (让 i = 0; i 

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 = "
--" + boundary + "
";
        const close_delim = "
--" + boundary + "--";
        var fileName='mychat123.png';
        var contentType='image/png'
        var metadata = {
          'name': fileName,
          'mimeType': contentType
        };

          var multipartRequestBody =
            delimiter +  'Content-Type: application/json

' +
            JSON.stringify(metadata) +
            delimiter +
            'Content-Type: ' + contentType + '
';

            multipartRequestBody +=  + '
' + 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;

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!!

解决方案

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 you want to use uploadType=multipart, please set multipart/form-data; boundary=### to the header as the content type. In your script, it seems that the content type is image/png.

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

Modified script:

From:

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

  var multipartRequestBody =
    delimiter +  'Content-Type: application/json

' +
    JSON.stringify(metadata) +
    delimiter +
    'Content-Type: ' + contentType + '
';

    multipartRequestBody +=  + '
' + 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
  });

To:

const boundary = '-------314159265358979323846';
const delimiter = "--" + boundary + "
";
const close_delim = "
--" + boundary + "--";
var fileName = 'mychat123.png';
var contentType = 'image/png';
var metadata = {'name': fileName,'mimeType': contentType};
var multipartRequestBody = delimiter +
'Content-Type: application/json

' +
JSON.stringify(metadata) + "
" +
delimiter +
'Content-Type: ' + contentType + '
' +
'Content-Transfer-Encoding: base64

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

  • In the upload of Drive API, in the current stage, it seems that both multipart/form-data and multipart/related can be used.

Note:

  • In this answer, it supposes that your access token can be used for uploading the file to Google Drive. Please be careful this.

Reference:

Added:

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.

This is your script in your comment.

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

Modification points:

  • At Drive API v3, the property for setting the filename is name.
  • uploadType=multipart is required to be used in the endpoint.
  • The base64 data is required to be converted to the blob.

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

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

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

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