I'm trying to send a spreadsheet file as Excel via mail. The mail is sent successfully but the file can't be opened due to incorrect format (I need an xlsx file.)
The code I used is below.
var folders = DriveApp.getFolderById('folder_id')
var files = folders.getFiles();
if (files.hasNext())
{
file = files.next();
url = file.getUrl();
var params = {
method: "get",
headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setContentType(MimeType.MICROSOFT_EXCEL).setName(fileName + ".xlsx");
MailApp.sendEmail(email_ids, 'Sample Subject', 'Mail with attachment', {
attachments: [blob],
name: 'Automatic Emailer Script',
cc:email_id
})
replace
url = file.getUrl();
with
url = SpreadsheetApp.openById(id).getUrl().replace(/edit$/, 'export?format=xlsx')
Related
I am trying to upload a text file to google drive via API call. I am working low level, so I don't use any external libraries. I send HTTPS Request, the file gets uploaded on Google Drive along with the content, but the document name is "Untitled". I am able to change the name in a separate HTTPS request using PATCH method, but I want to know if it is possible to set the name before sending the initial HTTPS request. Below is my the header file and HTTPS code I am sending, I would appreciate it if you can help me set the name anything other than "Untitled" .
const options = {
method: "POST",
headers: {
"Authorization": `${token_credential.token_type} ${token_credential.access_token}`,
"Content-Type":'text/plain' ,
},
body: {
name:"MyTextFile.txt"
}
}
let makeFileRequest=https.request(
sendDriveTask,
options,
(res, err) => {
if(err) {
console.log(err)
} else {
console.log("success", res.statusCode)
}
}
)
makeFileRequest.end(filecontent);
}
Below is the respond I get back from google drive:
{"kind":"drive#file","id":"1XBcb9q8Q__b6gIP0sH5oOhZOKQMezlIK","name":"Untitled","mimeType":"text/plain"}
From your showing script, I understood that you want to achieve your goal using https.request. In your situation, how about the following modification?
Modification points:
About I am trying to upload a text file to google drive via API call., when I saw your script, the text data is not included. If you want to create a text file with empty content, please modify the endpoint.
If you want to create a text file with the text content, please include the text data.
Modified script 1:
In this modification, a text file with empty content is created.
const https = require("https");
const token_credential = {
token_type: "Bearer",
access_token: "###", // Please set your access token.
};
const sendDriveTask = "https://www.googleapis.com/drive/v3/files";
const body = JSON.stringify({ name: "MyTextFile.txt" });
const options = {
method: "POST",
headers: {
Authorization: `${token_credential.token_type} ${token_credential.access_token}`,
"Content-Type": "application/json",
},
};
let makeFileRequest = https.request(sendDriveTask, options, (res) => {
res.on("data", (r) => {
console.log(r.toString());
});
res.on("end", () => {
console.log("Done.");
});
});
makeFileRequest.on("error", (e) => {
console.log(e.message);
});
makeFileRequest.write(body);
makeFileRequest.end();
When this script is run, a text file of "MyTextFile.txt" with empty content is created in the root folder.
Modified script 2:
In this modification, a text file with sample text content is created. In this case, the request body is sent as multipart/related.
const https = require("https");
const metadata = JSON.stringify({ name: "MyTextFile.txt" }); // Please set the file metadata.
const textData = "sample text data"; // Please set the sample text content.
const token_credential = {
token_type: "Bearer",
access_token: "###", // Please set your access token.
};
const sendDriveTask = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
const boundary = "sample123";
const body = [`--${boundary}\r\n`, "Content-Type: application/json; charset=utf-8\r\n\r\n", metadata + "\r\n", `--${boundary}\r\n`, "Content-Type: text/plain\r\n\r\n", textData + "\r\n", `--${boundary}--`].join("");
const options = {
method: "POST",
headers: {
Authorization: `${token_credential.token_type} ${token_credential.access_token}`,
"Content-Type": "multipart/related; boundary=" + boundary,
},
};
let makeFileRequest = https.request(sendDriveTask, options, (res) => {
res.on("data", (r) => {
console.log(r.toString());
});
res.on("end", () => {
console.log("Done.");
});
});
makeFileRequest.on("error", (e) => {
console.log(e.message);
});
makeFileRequest.write(body);
makeFileRequest.end();
When this script is run, a text file of "MyTextFile.txt" with the sample text of sample text data is created in the root folder.
Note:
This sample script supposes that your access token can be used for creating a file on Google Drive. Please be careful about this.
About the 2nd pattern, the maximum file size is 5 MB. When you want to upload more sizes, please use the resumable upload. Ref
References:
Files: create
Upload file data
i'm trying to upload my files as form-data, after i've created a scene. But I receive always the error "Specified Photoscene ID doesn't exist in the database" (which were created directly before).
My upload function:
// Upload Files
async function uploadFiles(access_Token, photoSceneId, files) {
try {
const params = new URLSearchParams({
'photosceneid': photoSceneId,
'type': 'image',
'file': files
})
const headers = Object.assign({
Authorization: 'Bearer ' + access_Token,
'Content-Type': 'multipart/form-data' },
files.getHeaders()
)
let resp = await axios({
method: 'POST',
url: 'https://developer.api.autodesk.com/photo-to-3d/v1/file',
headers: headers,
data: params
})
let data = resp.data;
return data;
} catch (e) {
console.log(e);
}
};
I've also tried a few varaints, e.g. adding the photosceneId to the form data (form.append(..), but doesn't works either.
Any helpful suggestion are appreciated. Thx in advance.
There might be two problems here.
First, I am not sure of it, as I don't have experience of URLSearchParams as a "packer" for POST requests. This might be the reason why you get "Specified Photoscene ID doesn't exist in the database" error - perhaps the way the data are serialized using URLSearchParams is not compatible.
The second problem, I am sure of it, is regarding the way you submit the files.
According to documentation, you have to pass the files one by one, like
"file[0]=http://www.autodesk.com/_MG_9026.jpg" \
"file[1]=http://www.autodesk.com/_MG_9027.jpg"
and not just passing an array to the "file" field.
Having this said, try this approach:
var axios = require('axios');
var FormData = require('form-data');
var fs = require('fs');
var data = new FormData();
var TOKEN = 'some TOKEN';
const photoSceneID = 'some_photoscene_id';
data.append('photosceneid', photoSceneID);
data.append('type', 'image');
data.append('file[0]', fs.createReadStream('/C:/TEMP/Example/DSC_5427.JPG'));
data.append('file[1]', fs.createReadStream('/C:/TEMP/Example/DSC_5428.JPG'));
data.append('file[2]', fs.createReadStream('... and so on ...'));
var config = {
method: 'post',
url: 'https://developer.api.autodesk.com/photo-to-3d/v1/file',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + TOKEN,
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Also, I always recommend instead of jumping right into the code, to check first the workflow using apps like Postman or Insomnia and then, after you validated the workflow (created the photoscene, all images were properly uploaded and so on), you can translate this into the code.
At the end of this blogpost you will find the link to alrady created Postman collection, but I highly recommend building your own collection, as part of the learning step.
This is the solution that worked for me. Please note that the upload should be limited by a maximum of 20 files per call.
// Upload Files
async function uploadFiles(access_Token, photoSceneId) {
try {
let dataPath = path.join(__dirname, '../../data')
let files = fs.readdirSync(dataPath)
var data = new FormData();
data.append('photosceneid', photoSceneId)
data.append('type', 'image')
for(let i=0; i < files.length; i++) {
let filePath = path.join(dataPath, files[i])
let fileName = 'file[' + i + ']'
data.append(fileName, fs.createReadStream(filePath))
}
const headers = Object.assign({
Authorization: 'Bearer ' + access_Token,
'Content-Type': 'multipart/form-data;boundary=' + data.getBoundary()},
data.getHeaders()
)
let resp = await axios({
method: 'POST',
url: 'https://developer.api.autodesk.com/photo-to-3d/v1/file',
headers: headers,
maxContentLength: Infinity,
maxBodyLength: Infinity,
data: data
})
let dataResp = resp.data;
return dataResp;
} catch (e) {
console.log(e);
}
};
I am using the Dropbox API with Node JS. I was able to upload files to my Dropbox using HTTP requests, but I am not able to download them with it. My intent is to use HTTP request to view content of the file in the dropbox.
This is the code for uploading files:
var request = require('request')
var fs = require('fs')
var token = "XXXXXXXXXXXXXXXXX"
var filename = "path/to/file/file.txt"
var content = fs.readFileSync(filename)
options = {
method: "POST",
url: 'https://content.dropboxapi.com/2/files/upload',
headers: {
"Content-Type": "application/octet-stream",
"Authorization": "Bearer " + token,
"Dropbox-API-Arg": "{\"path\": \"/files/"+filename+"\",\"mode\": \"overwrite\",\"autorename\": true,\"mute\": false}",
},
body:content
};
request(options,function(err, res,body){
console.log("Err : " + err);
console.log("res : " + res);
console.log("body : " + body);
})
Now what should the request function be for downloading this file? I was attempting something like this:
var request = require('request')
var fs = require('fs')
var token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
var filename = "path/to/file/file.txt"
var content = fs.readFileSync(filename)
options = {
method: "GET",
url: 'https://content.dropboxapi.com/2/files/upload',
headers: {
"Content-Type": "application/octet-stream",
"Authorization": "Bearer " + token,
"Dropbox-API-Arg": "{\"path\": \"/files/"+filename+"\",\"mode\": \"overwrite\",\"autorename\": true,\"mute\": false}",
},
};
request(options,function(err, res){
console.log("Err : " + err);
console.log("res : " + res);
})
But the res just gives object Object
How do I download the file?
You failed to download the file because the URL used(https://content.dropboxapi.com/2/files/upload) is incorrect. According to Dropbox API document, the correct URL endpoint is:
https://content.dropboxapi.com/2/files/download
However, it is better to use npm module such as dropbox to implement the requirement, as it has already wrapped the logic. The code would look like:
var fetch = require('isomorphic-fetch');
var Dropbox = require('dropbox').Dropbox;
var dbx = new Dropbox({ accessToken: 'YOUR_ACCESS_TOKEN_HERE', fetch: fetch });
dbx.filesDownload({path: '...'})
.then(function(data) {
...
});
i want to attach zip file. but it doesn't work any attachment.
here is my source code.
var express = require('express');
var router = express.Router();
var nodemailer = require('nodemailer');
var fs = require('fs');
var mailinfo = require('../config/mail_info').info;
var smtpTransport = nodemailer.createTransport({
host: mailinfo.host,
port: mailinfo.port,
auth: mailinfo.auth,
tls: mailinfo.tls,
debug: true,
});
router.post('/',function(req,res){
var emailsendee = req.body.emailAddress;
console.log(emailsendee);
var emailsubject = "Requested File";
var emailText = "test";
var emailFrom = 'test#test.com';
var mailOptions={
from : "test <test#test.com>",
to : emailsendee,
subject : emailsubject,
html : '<h1>' + emailText+ '</h1>';
attachments : [
{
filename : '',//i just put black make you understand esaily
path : ''//what i did is under this code
}
]
};
console.log(mailOptions);
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
res.end();
}else{
console.log(response);
res.end();
}
});
});
module.exports = router;
i tried these for attaching a file
enter code here
attachments:[{ fileName: 'test.log', streamSource: fs.createReadStream('./test.log'}]
it still sends a mail without attachment.
when this code can't read a file there is a error.
so i guess this isn't working because of reading a file.
and i read some questions on stackoverflow which has similar error with me.
i fixed path -> filepath
and fixed streamSource -> path
my nodemailer version is 4.0.1.
help me send a mail with zip file.
I'm using exactly the same version of nodemailer(4.0.1 at this moment) and I'm sending emails with attachments successfully.
Your first code snippet looks promising :)
But the second part
i tried these for attaching a file
enter code here
attachments:[{ fileName: 'test.log', streamSource: fs.createReadStream('./test.log'}]
doesn't look right at all ...
Please refer to nodemailer docs
fileName and streamSource are not a valid parameters of mailOptions object
EXAMPLE FROM DOCS
var mailOptions = {
...
attachments: [
{ // utf-8 string as an attachment
filename: 'text1.txt',
content: 'hello world!'
},
{ // binary buffer as an attachment
filename: 'text2.txt',
content: new Buffer('hello world!','utf-8')
},
{ // file on disk as an attachment
filename: 'text3.txt',
path: '/path/to/file.txt' // stream this file
},
{ // filename and content type is derived from path
path: '/path/to/file.txt'
},
{ // stream as an attachment
filename: 'text4.txt',
content: fs.createReadStream('file.txt')
},
{ // define custom content type for the attachment
filename: 'text.bin',
content: 'hello world!',
contentType: 'text/plain'
},
{ // use URL as an attachment
filename: 'license.txt',
path: 'https://raw.github.com/nodemailer/nodemailer/master/LICENSE'
},
{ // encoded string as an attachment
filename: 'text1.txt',
content: 'aGVsbG8gd29ybGQh',
encoding: 'base64'
},
{ // data uri as an attachment
path: 'data:text/plain;base64,aGVsbG8gd29ybGQ='
},
{
// use pregenerated MIME node
raw: 'Content-Type: text/plain\r\n' +
'Content-Disposition: attachment;\r\n' +
'\r\n' +
'Hello world!'
}
]
}
as you can see you should change fileName to filename and streamSource to content
// WRONG
attachments:[{ fileName: 'test.log', streamSource: fs.createReadStream('./test.log'}]
// RIGHT
attachments:[{ filename: 'test.log', content: fs.createReadStream('./test.log'}]
Good Luck! I hope this was helpful for you :)
I'm using version 2 of Box's API and attempting to upload files. I have Oauth 2 all working, but I'm having trouble making actual uploads.
I'm using Node.js and Express, along with the "request" module. My code looks something like this:
request.post({
url: 'https://upload.box.com/api/2.0/files/content',
headers: {
Authorization: 'Bearer ' + authToken
},
form: {
filename: ????,
parent_id: '0'
}
}, function (error, response, body) {
// ...
});
For now, I'm trying to upload to the root folder which, if I understand correctly, has an ID of '0'.
What I'm really not sure about is what value to give "filename". I don't have a true file to read from, but I do have a lengthy string representing the file contents I would like to upload.
How best should I upload this "file"?
For Box, I believe you want to use requests multi-part/form-data implementation.
It should look something like this:
var request = require('request');
var fs = require('fs');
var r = request.post(...);
var form = r.form();
form.append('filename', new Buffer("FILE CONTENTS"), {filename: 'file.txt'});
form.append('parent_id', 0);
var fs = require('fs');
var request = require('request');
var path = require('path');
function requestCallback(err, res, body) {
console.log(body);
}
var accessToken = 'SnJzV20iEUw1gexxxxvB5UcIdopHRrO4';
var parent_folder_id = '1497942606';
var r = request.post({
url: 'https://upload.box.com/api/2.0/files/content',
headers: { 'Authorization': 'Bearer ' + accessToken }
}, requestCallback);
var form = r.form();
form.append('folder_id', parent_folder_id);
form.append("filename", fs.createReadStream(path.join(__dirname, 'test.mp4')));