I was trying to write simple javascript code to convert and upload files to Google Drive using Drive REST api(So that only converted document to google document format will be uploaded). I got succided in uploading docx/xlsx/pptx documents however when I am trying to macro enabled files such as .docm/.pptm/.xlsm I am getting error "Bad Request" shown in screenshot:Error while uploading .docm file
My JavaScript code looks like:
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<input type="file" id="fileToUpload"></input>
<button onclick="insertFile()">Pick File to Upload</button>
<script type="text/javascript">
var CLIENT_ID = 'CLIENT_ID_HERE';
var SCOPES = 'https://www.googleapis.com/auth/drive';
var FOLDER_ID = '';
/**
* Called when the client library is loaded to start the auth flow.
*/
function handleClientLoad() {
window.setTimeout(checkAuth, 1);
}
/**
* Check if the current user has authorized the application.
*/
function checkAuth() {
gapi.auth.authorize(
{'client_id': CLIENT_ID, 'scope': SCOPES},
handleAuthResult);
}
/**
* Called when authorization server replies.
*
* #param {Object} authResult Authorization result.
*/
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
console.log("Auth OK !!!");
}
}
function insertFile() {
fileData = document.getElementById("fileToUpload").files[0];
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var reader = new FileReader();
reader.readAsBinaryString(fileData);
reader.onload = function(e) {
var contentType = fileData.type || 'application/octet-stream';
var metadata = {
'title': fileData.fileName,
'mimeType': contentType
};
var base64Data = btoa(reader.result);
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v2/files',
'method': 'POST',
'params': {'convert': true},
'headers': {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
},
'body': multipartRequestBody});
request.execute((file) => {
console.log(file);
});
}
}
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
EDIT:
Earlier I thought 'Google Drive does not support converting macro enabled files'. However when I tried to convert and upload the macro enabled files using python script I was able to do that . Python code:
http = httplib2.Http()
credentials.authorize(http)
drive_service = apiclient.discovery.build('drive', 'v2', http=http)
metadata = {'title': 'test_file.docm',
'mimeType' : 'application/vnd.ms-word.document.macroEnabled.12',}
res = drive_service.files().insert(convert='True',body=metadata,
media_body='test_file.docm', fields='mimeType,exportLinks').execute()
Am I missing anything in Javascript code?
Related
I am trying to send a PDF file as a base64 string to my drive folder using google drive API v3, but the only thing I get as a result is a file which displays the base64 string.
My code :
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
const metadata = {
'name': 'myFile.pdf',
'mimeType': 'application/pdf\r\n\r\n'
};
const multipartRequestBody = delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Encoding: ' + 'base64\r\n' +
'Content-Type: ' + 'application/pdf\r\n\r\n' +
data +
close_delim;
const request = auth.request({
url: 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart',
method: 'post',
headers: {
'Content-Type': `multipart/related; boundary=${boundary}`,
'Content-Length': multipartRequestBody.length
},
data: multipartRequestBody
});
const response = await request;
I've searched everywhere, tried a lot of combinations but I am not able to make this work. Does anyone have an idea?
I have used following code succesfully to send pdfs and other types of files to the Google drive:
var user = gapi.auth2.getAuthInstance().currentUser.get();
var oauthToken = user.getAuthResponse(true).access_token;
var boundary = 'foo_bar_baz';
var data = '--' + boundary + '\n';
data += 'content-type: application/json; charset=UTF-8' + '\n\n';
data += JSON.stringify(metadata) + '\n';
data += '--' + boundary + '\n';
var dataURLparts = file.data.split(',', 2);
var dataURLheaderParts = dataURLparts[0].split(':');
var dataURLheaderPayloadParts = dataURLheaderParts[1].split(';');
data += 'content-transfer-encoding: ' + dataURLheaderPayloadParts[1] + '\n';
data += 'content-type: ' + dataURLheaderPayloadParts[0] + '\n\n';
data += dataURLparts[1] + '\n';
data += '--' + boundary + '--';
console.log("uploading " + file.info.name);
$.ajax({
type: 'POST',
url: 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + oauthToken);
},
contentType: 'multipart/related; boundary=' + boundary,
data: data,
processData: false
}).done(function(response) {
console.log(response);
});
The file object in the example is from an HTML <input type="file"> element, so the content-type and the content-transfer-encoding can be get from the input element. There is other example where you can see what they look like for an image (base64 encoded): Send post request on Google API using javascript on browser. I am using jQuery to POST the data.
I want to upload a file to google drive with metadata, I am using the rest APIs and providing all the required details. The request is successfully completed, and files are created with the metadata, but the file size is just 13 byte.
here is the code
function addFileToFolder(arrayBuffer, i) {
var index = i;
var fileName = files[index].name;
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var fileContnet="this is the simple text file"
const contentType = 'application/json';
const contentTypeImage = 'application/octet-stream';
var metadata = {
'name': fileName,
'mimeType': contentTypeImage
};
var multipartRequestBody =
delimiter +
'Content-Type:application/json \r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentTypeImage + '\r\n\r\n' +
files[index] +
close_delim;
// var fileCollectionEndpoint ="https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
var len=(arrayBuffer.byteLength);
alert(len);
var request = gapi.client.request({
'path': '/upload/drive/v3/files',
'method': 'POST',
'params': {'uploadType': 'multipart'},
'headers': {
'Content-Type': 'multipart/related; boundary="' + boundary + '"',
'Content-Length':len
},
'body': multipartRequestBody});
request.execute(function(data){console.log(data)});
//----------------------
}
}
I tried various solutions.
I changed the arrayBuffer to files[i]
for Content-length I added (arrayBuffer.bytelength+metadata.lenght)
and (file[0].size+metadata.length)
but no luck
I tried a simple upload with no metadata, it works and a file is uploaded with untitled name.
is there any one who faces the same issue and can sugggest me the solution
I have create dynamical file and after I have to add some dynamic content from fckeditor put on that file on save button how to add content or text. Add on google document file using java script code of google drive API in PHP.
function gd_updateFile()
{
var my_text = "your content";
var folderId = "fileid";
var fileId = "your folder id ";
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var contentType = "text/html";
var metadata = {'mimeType': contentType,};
var multipartRequestBody =
delimiter + 'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter + 'Content-Type: ' + contentType + '\r\n' + '\r\n' +
my_text +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v2/files/'+folderId+"?fileId="+fileId+"&uploadType=multipart",
'method': 'PUT',
'params': {'fileId': fileId, 'uploadType': 'multipart'},
'headers': {'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'},
'body': multipartRequestBody,
callback:callback,
});
$(".update_file_out_put").html(callback);
if (!callback)
{
callback = function(file)
{
//console.log(file);
};
}
}
I'm wondering if it is possible to track the progress of a file upload to google cloud storage when using the javascript client? As I have a progress bar that I would like to show to the user on how much of the file has been uploaded so far.
I'm using the same upload code that google gives on their example page for file upload.
Instead of using the gapi.client.request api provided by the js library I instead created an XMLHttpRequest and appended a event listener for the event progress. As seen by the following:
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var reader = new FileReader();
reader.readAsBinaryString(fileData);
reader.onload = function(e) {
var contentType = fileData.type || 'application/octet-stream';
var metadata = {
'name': 'testing',
'mimeType': contentType
};
var base64Data = btoa(reader.result);
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
gapi.client.request()
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.googleapis.com/upload/storage/v1/b/bucket/o?uploadType=multipart&key=apiKey&alt=json', true);
xhr.setRequestHeader('Content-Type', 'multipart/mixed; boundary="' + boundary + '"');
xhr.setRequestHeader('authorization', 'Bearer ' + gapi.auth.getToken().access_token);
xhr.upload.addEventListener("progress", function(e) {
var pc = parseFloat(e.loaded / e.total * 100).toFixed(2);
}, false);
xhr.onreadystatechange = function(e) {
if (xhr.readyState == 4) {
console.log(xhr.responseText);
}
};
xhr.send(multipartRequestBody);
Attribution: Majority of code was taken from Google's js library with the only addition being the event listener for listening to the progress of the upload.
I'm trying to use javascript in order to set the contents of a file stored on Google Drive (for example, a .txt or .java file) to a specific String.
I know that the proper way to update a file stored on Google Drive is
function updateFile(fileId, fileMetadata, fileData, callback) {
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
//console.log("fileId: "+fileId+" fileData: "+fileData);
var reader = new FileReader();
reader.readAsBinaryString(fileData);
reader.onload = function(e) {
console.log("reader initialized");
var contentType = fileData.type || 'application/octet-stream';
// Updating the metadata is optional and you can instead use the value from drive.files.get.
var base64Data = btoa(reader.result);
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(fileMetadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v2/files/' + fileId,
'method': 'PUT',
'params': {'uploadType': 'multipart', 'alt': 'json'},
'headers': {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
},
'body': multipartRequestBody});
if (!callback) {
callback = function(file) {
console.log(file)
};
}
request.execute(callback);
}
}
but this has not worked in setting the content to a specific String.
Never mind. I found the answer to my problem. Using the method updateFile from my question:
function save(fileId, content){
var contentArray = new Array(content.length);
for (var i = 0; i < contentArray.length; i++) {
contentArray[i] = content.charCodeAt(i);
}
var byteArray = new Uint8Array(contentArray);
var blob = new Blob([byteArray], {type: 'text/plain'});
var request = gapi.client.drive.files.get({'fileId': fileId});
request.execute(function(resp) {
updateFile(fileId,resp,blob,changesSaved);
// the callback^^^^^^
});
}