Uploading File to specific folder in Google drive in Angular 4 - javascript

I am trying to upload a file to a specific folder, but I am unable to do it.
Uploading is working correctly but it is not putting a file in a particular folder.
I am trying to do a Resumable upload with google drive rest version 3.
Assuming I already have a Folder ID.
First getting uploading URI :
uploadFileToDrive(name: string, content: string): Promise<Object> {
const url = `https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable`;
const accessToken = localStorage.getItem('accessToken');
let headers = new Headers({
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + accessToken,
});
let options = new RequestOptions({ headers: headers }); // Create a request option
return this.http
.post(url, { name: name, role: 'reader', type: 'anyone', 'parents': [{"id":parentId}] }, options)
.toPromise()
.then(response => this.gDriveUploadFile(content, response.headers.get('location')));
}
Second uploading media :
gDriveUploadFile(file, url): Promise<any> { //file and url we got from first func
console.log(file + " "+ url );
const accessToken = localStorage.getItem('accessToken');
let headers = new Headers({
'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/json; charset=UTF-8',
'X-Upload-Content-Type': file.type ,
});
let options = new RequestOptions({ headers: headers }); // Create a request option
return this.http.post(`${url}`, file, options) //call proper resumable upload endpoint and pass just file as body
.toPromise()
}
Also, I would like to know how I will be able to create a folder using google rest API in angular.

Related

Google docs api error- while trying to update a files title the outcome is a file with my request body params written in it

the code is supposed to make a copy of a document and then change its title, instead it created a document and then change the entire body of the document to the body fields i sent in the request instead of updating the title.
function createFilewithtemplate(tag,document_id){
var accessToken = gapi.auth.getToken().access_token;
var fileName= "Wib Issues Report - "+tag +' '+ getDateString()
console.log(accessToken)
fetch('https://www.googleapis.com/drive/v3/files/'+document_id+'/copy',{
method: "POST",
headers: new Headers({ 'Authorization': 'Bearer '+ accessToken}),
}).then( (res) => {
return res.json();
}).then( function(val) {
fetch('https://www.googleapis.com/upload/drive/v2/files/'+val.id,{
method: "PUT",
headers: new Headers({ 'Authorization': 'Bearer '+ accessToken}),
body: JSON.stringify('title' : 'new file')
})
console.log(val);
console.log(val.id);
window.open("https://docs.google.com/document/d/" + val.id + "/edit");
});
document
I believe your goal is as follows.
You want to copy a Google Document and want to rename the copied Document.
In this case, when your showing script is modified, how about the following modification?
Modified script:
var accessToken = gapi.auth.getToken().access_token;
var fileName= "Wib Issues Report - "+tag +' '+ getDateString();
fetch('https://www.googleapis.com/drive/v3/files/'+document_id+'/copy',{
method: "POST",
headers: {
"Authorization": "Bearer "+ accessToken,
"Content-Type": "application/json",
},
body: JSON.stringify({name: fileName})
})
.then(res => res.json())
.then(res => {
console.log(res);
console.log(res.id);
window.open("https://docs.google.com/document/d/" + res.id + "/edit");
});
In this modification, the Document is copied and renamed using the method of "Files: copy" in Drive API.
Reference:
Files: copy

How to rewrite angular ng-file-upload Upload.upload with JS fetch?

I need to upload file to server using fetch() from react native app
I have the following code in Angular which uses ng-file-upload:
in this function file variable is attached FormData
function addDocumentToMessage(messageId, file) {
data.filepath = file;
data.name = file.name;
return Upload.upload({
url: BackendUrl + "/messages/" + messageId + "/attachments/",
file: file,
data: data
})
.then(responseHandler)
.catch(errorHandler);
}
I tried to do following using fetch() but it doesn't work correctly: file is added to server but attachment and other fields are not saved there. Here is the code I tried:
document = { formData, name }
export const addDocumentToMessage = (token, logId, document) => {
const file = document.formData
const data = { filepath: file, name: document.name }
fetch(`${API_URL}/messages/${logId}/attachments/`, {
method: 'POST',
headers: { 'Authorization': `token ${token}`, 'Content-Type': 'multipart/form-data', Accept: 'application/json' },
body: JSON.stringify({ file: file, data: data })
})
.then(response => console.log(response.data))
.catch(error => console.log(error.message))
}
It seems that two Content-Types were mixed here:
multipart/form-data for sending binary content of the file in file
application/json for sending the some JSON data in body
Since HTTP requests only support one body having one Content-Type encoding we have to unify all of that to be multipart/form-data. The following example is using variable formData to combine (binary) file data with arbitrary JSON data.
export const addDocumentToMessage = (token, logId, document) => {
// commented these lines since I wanted to be more specific
// concerning the origin and types of data
// ---
// const file = document.formData
// const data = { filepath: file, name: document.name }
const fileField = document.querySelector("input[type='file']");
let formData = new FormData();
formData.append('file', fileField.files[0]);
formData.append('name'. fileField.files[0].name);
formData.append('arbitrary', JSON.stringify({hello: 'world'}));
fetch(`${API_URL}/messages/${logId}/attachments/`, {
method: 'POST',
headers: {
'Authorization': `token ${token}`,
'Accept': 'application/json'
// 'Content-Type': 'multipart/form-data',
},
body: formData
})
.then(response => console.log(response.data))
.catch(error => console.log(error.message))
}
The payload of HTTP request body would then look like this:
------WebKitFormBoundarypRlCB48zYzqAdHb8
Content-Disposition: form-data; name="file"; filename="some-image-file.png"
Content-Type: image/png
... (binary data) ...
------WebKitFormBoundarypRlCB48zYzqAdHb8
Content-Disposition: form-data; name="name"
some-image-file.png
------WebKitFormBoundarypRlCB48zYzqAdHb8
Content-Disposition: form-data; name="arbitrary"
{"hello":"world"}
------WebKitFormBoundarypRlCB48zYzqAdHb8--
References:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Uploading_a_file
https://developer.mozilla.org/de/docs/Web/API/FormData/append#Syntax

How to download ZIP file from reactjs using post api?

How to download zip file from reactjs using POST API.
The request is coming from nodejs in binary form
you can use jszip link https://github.com/Stuk/jszip like
import zipTargetFiles from '/path'
zipTargetFiles( data ).then(file => {
//operations
})
if you use fetch like this.
fetch('URL', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
//Body
})
}).then((response)=>{
//here is youu want zip data
var zip = new JSZip();
var zipData = response.data //
// Add an top-level, arbitrary text file with contents
zip.file("response.txt", zipData);
// Generate the zip file asynchronously
zip.generateAsync({type:"blob"})
.then(function(content) {
// Force down of the Zip file
saveAs(content, "zipFile.zip");
});
}).catch((error)=>{
console.log(error)
})
You can use JsZip on Client Side. Then, do a request with axios. Like this:
request = (currentUrl: string): Promise<void> => axios({
url: currentUrl,
method: 'GET',
responseType: 'blob',
}).then((response) => {
const url: string = window.URL.createObjectURL(new Blob([response.data]));
});

Google Drive Rest API

I am running into a problem with google drive rest api. I have a button and upon the user click, I get a blob excel file from my backend and upload the file to google drive. The file is being uploaded to the google drive, but when I opened it, it says '[object blob]'. The actual content isn't in the file. Here is my function for creating the file. I found this solution from here: Create File with Google Drive Api v3 (javascript)
var UploadExcelFile = function(name, data, callback){
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
const contentType = "application/vnd.google-apps.spreadsheet";
var metadata = {
'name': name,
'mimeType': contentType
};
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n\r\n' +
data +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v3/files',
'method': 'POST',
'params': {'uploadType': 'multipart'},
'headers': {
'Content-Type': 'multipart/related; boundary="' + boundary + '"'
},
'body': multipartRequestBody});
if (!callback) {
callback = function(file) {
console.log(file)
};
}
request.execute(callback);
}```
```This is the response from the server:
Response {type: "basic", url:
"http://localhost:54878/home/generateexcel", redirected: false,
status:
200, ok: true, …}
body: ReadableStream
locked: true
__proto__: ReadableStream
bodyUsed: true
headers: Headers
__proto__: Headers
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:54878/home/generateexcel"}
I am passing in the name of the file and the blob excel file from the backend like so:
fetch('/home/generateexcel', {
method: 'POST',
body: JSON.stringify(postData),
headers: {
"Content-Type": "application/json"
},
}).then(function (response) {
response.blob().then(function (result)
UploadExcelFile('newfile', result)
});
}).catch(function (err) {
// Error :(
});
You want to upload the downloaded xlsx file to Google Drive.
You have already confirmed that the xlsx file could be downloaded.
When a xlsx file is uploaded, you want to convert to Google Spreadsheet.
You can use Drive API and the access token for uploading files.
If my understanding is correct, how about this modification? In this modification, I used FormData() for creating the request body and used fetch() for requesting to Drive API. I think that there are several solutions for your situation. So please think of this as just one of them.
Modified script:
I modified UploadExcelFile(). Please modify as follows and try again.
function UploadExcelFile(name, data) {
var metadata = {
name: name,
mimeType: "application/vnd.google-apps.spreadsheet",
};
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
form.append('file', data);
fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,kind', {
method: 'POST',
headers: new Headers({'Authorization': 'Bearer ' + gapi.auth.getToken().access_token}),
body: form
}).then((res) => {
return res.json();
}).then(function(val) {
console.log(val);
});
}
In my environment, I could confirm that this script worked. But if this didn't work in your environment, I apologize.

Google Drive API and file uploads from the browser

I'm trying to upload a file with the Google Drive api, and I have the metadata correct, and I want to ensure that the actual file contents make it there. I have a simple page setup that looks like this:
<div id="upload">
<h6>File Upload Operations</h6>
<input type="file" placeholder='file' name='fileToUpload'>
<button id='uploadFile'>Upload File</button>
</div>
and I have a the javascript setup where the user is prompted to sign in first, and then they can upload a file. Here's the code: (currently only uploads the file metadata....)
let uploadButton = document.getElementById('uploadFile');
uploadButton.onclick = uploadFile;
const uploadFile = () => {
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
console.dir(ftu);
gapi.client.drive.files.create({
'content-type': 'application/json;charset=utf-8',
uploadType: 'multipart',
name: ftu.name,
mimeType: ftu.type,
fields: 'id, name, kind'
}).then(response => {
console.dir(response);
console.log(`File: ${ftu.name} with MimeType of: ${ftu.type}`);
//Need code to upload the file contents......
});
};
First, I'm more familiar with the back end, so getting the file in bits from the <input type='file'> tag is a bit nebulous for me. On the bright side, the metadata is there. How can I get the file contents up to the api?
So According to some resources I've found in my three day search to get this going, the file simply cannot be uploaded via the gapi client. It must be uploaded through a true REST HTTP call. So let's use fetch!
const uploadFile = () => {
//initialize file data from the dom
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
let file = new Blob([ftu]);
//this is to ensure the file is in a format that can be understood by the API
gapi.client.drive.files.create({
'content-type': 'application/json',
uploadType: 'multipart',
name: ftu.name,
mimeType: ftu.type,
fields: 'id, name, kind, size'
}).then(apiResponse => {
fetch(`https://www.googleapis.com/upload/drive/v3/files/${response.result.id}`, {
method: 'PATCH',
headers: new Headers({
'Authorization': `Bearer ${gapi.client.getToken().access_token}`,
'Content-Type': ftu.type
}),
body: file
}).then(res => console.log(res));
}
The Authorization Header is assigned from calling the gapi.client.getToken().access_token function, and basically this takes the empty object from the response on the gapi call and calls the fetch api to upload the actual bits of the file!
In your situation, when you upload a file using gapi.client.drive.files.create(), the empty file which has the uploaded metadata is created. If my understanding is correct, how about this workaround? I have experienced the same situation with you. At that time, I used this workaround.
Modification points:
Retrieve access token using gapi.
File is uploaded using XMLHttpRequest.
Modified script:
Please modify the script in uploadFile().
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
var metadata = {
'name': ftu.name,
'mimeType': ftu.type,
};
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', ftu);
var xhr = new XMLHttpRequest();
xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,kind');
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.responseType = 'json';
xhr.onload = () => {
console.log(xhr.response);
};
xhr.send(form);
Note:
In this modified script, it supposes that Drive API is enabled at API console and the access token can be used for uploading file.
About fields, you are using id,name,kind. So this sample also uses them.
Reference:
gapi
If I misunderstand your question or this workaround was not useful for your situation, I'm sorry.
Edit:
When you want to use fetch, how about this sample script?
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
var metadata = {
'name': ftu.name,
'mimeType': ftu.type,
};
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', ftu);
fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,kind', {
method: 'POST',
headers: new Headers({'Authorization': 'Bearer ' + accessToken}),
body: form
}).then((res) => {
return res.json();
}).then(function(val) {
console.log(val);
});
With https://www.npmjs.com/package/#types/gapi.client.drive
const makeUploadUrl = (fileId: string, params: Record<string, boolean>) => {
const uploadUrl = new URL(
`https://www.googleapis.com/upload/drive/v3/files/${fileId}`
)
Object.entries({
...params,
uploadType: 'media',
}).map(([key, value]) => uploadUrl.searchParams.append(key, `${value}`))
return uploadUrl
}
const uploadDriveFile = async ({ file }: { file: File }) => {
const params = {
enforceSingleParent: true,
supportsAllDrives: true,
}
// create file handle
const { result } = await gapi.client.drive.files.create(params, {
// CAN'T have the upload type here!
name: file.name,
mimeType: file.type,
// any resource params you need...
driveId: process.env.DRIVE_ID,
parents: [process.env.FOLDER_ID],
})
// post the file data
await fetch(makeUploadUrl(result.id!, params), {
method: 'PATCH',
headers: new Headers({
Authorization: `Bearer ${gapi.client.getToken().access_token}`,
'Content-Type': file.type,
}),
body: file,
})
return result
})
}

Categories