upload blob to google drive using google drive api in javascript - javascript

i am able to upload blob to google drive using google drive api, but failing to assign filename and filepath
fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=media',{
method:'post',body:imgBlob,headers:{
'Content-Type': 'image/webp',
'Content-Disposition':`attachment;filename=${fileName}`,
'Authorization':`Bearer ${accessToken}`
}
}).then(req=>req.json()).then(res=>console.log(res)).catch(error=>console.log(error))
please assist

I believe your goal is as follows.
You want to upload a blob to Google Drive by giving the file metadata of the filename and the folder using the fetch API of Javascript
Your access token can be used for uploading a file to Google Drive.
In this case, how about the following modification?
Modified script
const folderId = "###"; // Please set your folder ID.
const filename = "###"; // Please set filename on Google Drive.
const accessToken = "###"; // Please set your access token.
const form = new FormData();
form.append('metadata', new Blob([JSON.stringify({ name: fileName, parents: [folderId] })], { type: 'application/json' }));
form.append('file', imgBlob);
fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart', {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}` },
body: form
}).then(res => res.json()).then(res => console.log(res));
Note:
In this case, the maximum file size is 5 MB. If you want to upload a large file size, please use the resumable upload. Please be careful about this.
If the destination folder is in the shared Drive, please add supportsAllDrives=true to the query parameter of the endpoint.
Reference:
Upload file data

Related

403 on `PUT` request on signed url for S3 image upload using lamda

I was trying to create an image uploader to my S3 bucket using a Lambda. But when I try to do a PUT request on the generated signed URL from the lambda I am getting a 403.
I have configured my lambda to be able to s3:putObject and s3:putObjectACL
I have also tried to make my s3 bucket public to allow read and write to it for Everyone and have also enabled CORS on my s3 bucket along with my API lambda trigger endpoint.
I am still getting a 403 forbidden when I try to upload an image from my client-side HTML page.
The function is like this:
const uploadS3 = async (uri) =>{
const file = new Image();
file.src = uri;
const url = "API-Endpoint to trigger LAMBDA";
fetch(url,
{
//fetches the signed url
method: 'GET',
mode:'cors',
})
.then((res) => res.json())
.then((response)=> {
console.log(response);
console.log(response.uploadURL);
// request to try to PUT image to s3 bucket using the signed url
fetch(response.uploadURL,{
method: 'PUT',
headers: {
"Content-Type": "image/png"
},
mode:'cors',
body: file
})
.then((res)=> console.log(res))
.catch((res)=> console.log(res))
})
.catch((err)=>console.log(err))
}
Where am I going wrong?
Really thankful for your help !!
You need the following headers both when getting the presigned URL on server side and when making the request on the client side with the presigned URL
{ headers: { 'Content-Type': 'image/jpeg', 'x-amz-acl': 'public-read' } };

How to download file in memory and then upload it to somewhere else

I would like to do create a tempermonkey script that would download a file on a site without bothering the user with saving it on the disk. So the file would be stored in a variable, which the script would be able to use to upload that file to my remote server.
Is it possible to do in browser javascript?
Diagram:
One option would be to download the file as a blob using fetch:
async function upload() {
const res = await fetch('https://example.com/download-endpoint')
const blob = await res.blob()
fetch('https://example.com/upload-endpoint', {
method: 'POST',
headers: {
'Content-Type': blob.type
},
body: blob
})
}

Google Drive API V3 Javascript - Create File with Content

This question has been asked before, but the answer was using API V2. The google documentation does not clarify how to create a file with its content using javascript client code. I tried using the code listed under Node, however, it only creates the file, it does not insert any content. Here is my code:
let fileMetadata = {
'name': name,
parents: [parentId]
};
let media = {
mimeType: 'text/plain',
body: 'content inside file'
};
gapi.client.drive.files.create({
resource: fileMetadata,
media,
fields: 'id'
})
.then(response => {
console.log('response: ', response);
})
.catch(() => {
console.log('something is wrong');
});
Can someone help me insert content into files please?
How about this sample script? In my environment, although gapi.client.drive.files.create() can create an empty file on Google Drive, it cannot directly upload files including contents. I think that this might not be able to upload files and metadata with the multipart/related, although this might be resolved by the future update. So now, as one of workarounds, I use XMLHttpRequest.
Before you use this sample script, please confirm the following points.
In your situation, you have already been able to create files using gapi. In my script, the access token is retrieved using gapi.
When you use this script, please set fileContent and metadata.
Sample script :
In this sample script, a text file including contents is created under a folder.
var fileContent = 'sample text'; // As a sample, upload a text file.
var file = new Blob([fileContent], {type: 'text/plain'});
var metadata = {
'name': 'sampleName', // Filename at Google Drive
'mimeType': 'text/plain', // mimeType at Google Drive
'parents': ['### folder ID ###'], // Folder ID at Google Drive
};
var accessToken = gapi.auth.getToken().access_token; // Here gapi is used for retrieving the access token.
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
form.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id');
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.responseType = 'json';
xhr.onload = () => {
console.log(xhr.response.id); // Retrieve uploaded file ID.
};
xhr.send(form);
Request body :
In this script, form is as follows. This is sent to Google Drive using the create method of Drive API.
------WebKitFormBoundaryxX0XmxgooMjdUECR
Content-Disposition: form-data; name="metadata"; filename="blob"
Content-Type: application/json
{"name":"sampleName","mimeType":"text/plain","parents":["#####"]}
------WebKitFormBoundaryxX0XmxgooMjdUECR
Content-Disposition: form-data; name="file"; filename="blob"
Content-Type: text/plain
sample text
------WebKitFormBoundaryxX0XmxgooMjdUECR--
In my environment, I confirmed that this works fine. But if this didn't work in your environment, I'm sorry.

Dealing with encoding in Flask file uploads/downloads

I have a react client that takes in user input as a file and sends it to my remote Flask server for storage. I send the file in the form of a Werkzeug FileStorage object and in the remote server I store it with file.save(path). In the react client I'm trying to build a way to download the file from the server, however I'm running into problems. Currently my program is working for downloading .txt files. I'm able to do this though a fetch javascript request:
fetch(FETCH_URL, {
method: 'POST',
body: data,
headers: {
'Content-Type': 'application/json'
}
}).then((response) => {
var a = response.body.getReader();
a.read().then(({ done, value }) => {
saveAsFile(new TextDecoder("utf-8").decode(value), 'filename.txt');
}
);
});
function saveAsFile(text, filename) {
const type = 'application/text'; // modify or get it from response
const blob = new Blob([text], {type});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
}
Thanks to some help I got in this post: Download file in react client from flask remote server
I know this code is specifically made to work only with .txt files based on the type being passed in to Blob, but the front end is not the real problem.
The real problem is in my remote flask server, the following code is what is called in the flask server:
with open(filename, 'r') as f:
contents = f.read()
return contents
I tried returning the file itself but the server gives an error:
"ValueError: I/O operation on closed file."
So I decided to return the contents of the file as shown above.
The problem arises when I try to get a file for example "download.jpeg". Reading the file gives the following error:
"UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte"
From what I understand Flask works exclusively with 'utf-8' and I assume this means the file in the server is on 'utf-8' encoded.
Does anyone have a suggestion or guidance on a solution or a workaround maybe a way to change the files encoding when I save it on the server or something else that could help me with what I'm trying to do?
Fetch's Response has blob() to convert the response directly to blob, so you don't have to read the stream, you don't have to find out it's content type or anything. Just try the below solution.
fetch(FETCH_URL, {
method: 'POST',
body: data,
headers: {
'Content-Type': 'application/json'
}
}).then((response) => {
response.blob().then((blob) => {
saveBlob(blob, 'filename');
});
});
function saveBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
}
Try this: make sure to install axios. Also you probably won't have to deal with content type like above said. Obviously changing the method type to POST and bring ur data in.
axios(FETCH_URL, {
method: 'GET',
responseType: 'blob', // important
}).then((response) => { //Creates an <a> tag hyperlink that links the excel sheet Blob object to a url for downloading.
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `${Date.now()}.xlsx`); //set the attribute of the <a> link tag to be downloadable when clicked and name the sheet based on the date and time right now.
document.body.appendChild(link);
link.click(); //programmatically click the link so the user doesn't have to
document.body.removeChild(link);
URL.revokeObjectURL(url); //important for optimization and preventing memory leak even though link element has already been removed.
});

Can't correctly use fetch to PUT file on S3

Using a pre-signed URL I am trying to PUT an object (an image) in my AWS S3 bucket using JavaScript's fetch.
Below is the snippet of code I'm using, triggered by a change event on a file upload input.
// The event here is from a change
// trigger on the file input
const target = event.target
const file = target.files[0]
const reader = new FileReader()
reader.onload = (event) => {
fetch(PRESIGNED_S3_URL, {
method: 'put',
body: event.target.result,
headers: new Headers({
'Content-Type': file.type
}),
}).then((response) => {
response.json().then((data) => {
// Success
})
})
}
// Read the selected file
reader.readAsText(file)
This does indeed upload the file, setting its name and filetype correctly, but when I try to view the file it is corrupt.
I am stuck on what I am doing incorrectly to read and upload the file contents. Any help is appreciated!
To upload an image, you need to set content handling to CONVERT_TO_BINARY.

Categories

Resources