2

I have uploaded a base64 img string to Google Drive via API in node express. After uploading the img, it is not viewable in Drive. I'm not sure on how to resolve this formatting issue. I know I could potentially save the img locally first, then upload the saved img file but I was hoping there is a simpler way.

My code:

 const uploadImg = async (folderId,img)=>{


 process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0


 const scopes = [
     'https://www.googleapis.com/auth/drive'
 ];
 const auth = new google.auth.JWT(
     demoApiCreds.client_email, null,
     demoApiCreds.private_key, scopes
 );

 const drive = google.drive({ version: 'v3', auth });

 const fileMetadata = {
     'name': 'Client_Design_ScreenShotTest',
     'mimeType':'image/jpeg',
     'parents':[folderId]
 };


const uploadImg = img.split(/,(.+)/)[1];

const media = {
     body: uploadImg
 }

 let res = await drive.files.create({
     resource: fileMetadata,
     media: media,
     fields: 'id',
 });
 console.log('the response is',res);
 console.log('the data is ',res.data);
 return res.data;

}

Edit:

The file is stored in drive, as a jpg, but the img is blank and after the img is clicked google drive complains that the file cannot be read. The img is still blank after downloading.

The base 64 img string is

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhAAAADqCAYAAADzlnzfAAAAAXNSR0I...

I remove data:image/png;base64 before uploading as has been suggested in other threads. It fails with or without this prefix.

  • What formatting issue are you referring to? Also, are you getting an error when uploading or it is successful and yet you still cant view it in the drive. Also, what do you mean by viewable? As in you don't see the uploaded item entry at all or just the image is blank? Can you post the literal value of an actual image base 64? – 10100111001 Oct 05 '19 at 18:31
  • Edited my question to include some of the specifics you asked for. – Jonathan Davis Oct 05 '19 at 19:13
  • Can you post valid code as you have it as the second part is invalid (syntax errors, incomplete, and not using the `uploadImg` variable) – 10100111001 Oct 05 '19 at 19:25
  • Posted these changes, thanks. – Jonathan Davis Oct 05 '19 at 20:30

3 Answers3

5
  • You want to upload an image to Google Drive using googleapis with node.js.
  • The image of img is the base64 data.
  • You have already been able to upload and download files to Google Drive using Drive API.

If my understanding is correct, how about this answer? Please think of this as just one of several answers.

Modification points:

  • Unfortunately, when the base64 data is uploaded using googleapis, the base64 data is not decoded and the data is upload as the text data. So when you see the uploaded file, you cannot see it as the image. If Content-Transfer-Encoding: base64 can be added to the header of the base64 data in the request body, the base64 data is converted and uploaded as an image. But when googleapis is used, in the current stage, it cannot be achieved.

In order to upload the base64 data encoded from an image as an image to Google Drive, how about the following modification?

Modified script:

In this modification, the base64 image is converted to the stream type, and uploaded. Please modify your script as follows.

From:
const uploadImg = img.split(/,(.+)/)[1];

const media = {
  body: uploadImg
}
To:
const stream = require("stream"); // Added

const uploadImg = img.split(/,(.+)/)[1];
const buf = new Buffer.from(uploadImg, "base64"); // Added
const bs = new stream.PassThrough(); // Added
bs.end(buf); // Added

const media = {
  body: bs // Modified
};

Note:

  • Even if 'mimeType':'image/jpeg' is used at fileMetadata, the image file is uploaded as image/png. But for example, if 'mimeType':'application/pdf' is used at fileMetadata, the image file is uploaded as application/pdf. Please be careful this. So I also recommend to modify to 'mimeType':'image/png' as mentioned by 10100111001's answer.
  • At "googleapis@43.0.0", both patterns of resource: fileMetadata and requestBody: fileMetadata work.

References:

If I misunderstood your question and this was not the direction you want, I apologize.

Tanaike
  • 181,128
  • 11
  • 97
  • 165
0

You need to change your mimeType to image/png.

See here what Mime Types are

Edit: The property name for the fileMetadata is called requestBody instead of resource.

let res = await drive.files.create({ requestBody: fileMetadata, media: media, fields: 'id', });

https://github.com/googleapis/google-api-nodejs-client/blob/7e2b586e616e757b72f7a9b1adcd7d232c6b1bef/src/apis/drive/v3.ts#L3628

10100111001
  • 1,832
  • 1
  • 11
  • 7
0

I had the same problem, Solved it by adding "Content-Transfer-Encoding: base64"in body where we write body-request, content-type, etc.

sam_urai
  • 76
  • 4