Comment télécharger une image sur Google Drive à l'aide de Gapi et réagir
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!!
Points de modification:
- D'après votre script, il semble que ce
this.state.body
soit les données base64. Dans ce cas, il est nécessaire d'ajouterContent-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
.
- Et faites attention aux sauts de ligne du corps de la requête pour
- Lorsque vous souhaitez utiliser
uploadType=multipart
, veuillez définirmultipart/form-data; boundary=###
l'en-tête comme type de contenu. Dans votre script, il semble que le type de contenu soitimage/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-data
etmultipart/related
peuvent ê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 fetch
place 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.
- Pour cela, j'ai renvoyé cette réponse .
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) });