DataURL via AJAX to sails endpoint - javascript

I have a client side component that produces a DataURL (i.e. a user uploads or snaps a picture and then crops it). I need to post that via an AJAX call to a sails endpoint. From the sails docs, the endpoint is supposed to read the files like so:
req.file('file_name');
I am stuck on how I am supposed to go from DataURI -> AJAX call formatted so that the endpoint will be able to read the file from req.file. I guess I just need to see an implementation of the call being setup in any javascript/framework library so that I can implement.
Thanks a lot.

On the client-side you'll need to convert the DataURL into form data. There are a couple examples here and here and send it to the route in your controller.
Your endpoint will be a route that looks a bit like this:
var uploadHandlier = function(req, res)
{
req.file('avatar').upload(
{
// don't allow the total upload size to exceed ~4MB
maxBytes: 4000000,
dirname: '/tmp' // some temp directory
}, function whenDone(error, uploadedFiles)
{
if (error)
{
if (error.code === 'E_EXCEEDS_UPLOAD_LIMIT')
{
return res.badRequest(
{
msg: error.message
});
}
return res.serverError(error);
}
if (_.isEmpty(uploadedFiles))
{
res.badRequest(
{
msg: "No file was uploaded."
});
return;
}
var filePath = uploadedFiles[0].fd;
var fileType = uploadedFiles[0].type;
if (!_.includes(['image/jpeg', 'image/png', 'image/gif'], fileType))
{
res.badRequest(
{
msg: "Invalid file type."
});
return;
}
// do your thing...
});
};

Related

Is there a way to send data from a js file to the express server without using a form?

I am new here, Sorry if I miss something from the best practices.
I'm creating a sudoku game, using express, js, html and mongoDb.
Now I'm trying to create a statistics system. I would like to send a data when you wins the sudoku, to the express server (server.js) and after update the mongoDb.
I know I can send a data with the POST method, but I only know using the form html, but in this case I want to send it by the function js.
The js file: game.js
let cells = document.querySelectorAll('.div-cell'); // get the cells of the sudoku board
function checkWin() {
const db = getDb() // get the localStorage db (there is sudoku informationo, like the solution)
curentBoard = ''
for (let i = 0; i < 81; i++) {
if (cells[i].textContent === '') { // check if the cell is blank
curentBoard += '-'
} else {
curentBoard += cells[i].textContent
}
}
if (curentBoard === db.solution) { //check if the board is equal the solution
// Here would be the code to send the data to the server
alert('You won!')
newGame()
}
}
I've tried to use export to send the function to the server.js, to change the information, but I can't because the game.js is linked to the game.html, and for some reason the export doesn't work. Also for import.
I also tried to use ejs files, I rendered the ejs file sending the data statistics, by the server.js (express) but I couldn't change any data in the ejs file.
Then I tried to research other methods to make this, but I didn't find anything
Is there a way to send a data to the server.js by that function?
Here is an example of sending a post request with some data to the backend then sending back a response data from backend to frontend.
//front end
fetch('api/server', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
myData: "test"
})
})
.then((res) => res.json())
.then(data => {
if (data.status == 'success') {
//when data is returned from backend
const response = data.response
console.log(response) //should print dataReceived
}
})
//backend
const handler = async(req, res) => {
//accessing data sent from front end
const body = req.body
//should print test
console.log(body.myData)
//returning data back to frontend
return res.json({
status: 'success',
response: 'dataRecieved'
})
}
Yes, you can use fetch API inside your function to send POST request to your server. You need to send the data in the format that server expects (e.g. JSON)
here is an example of sending post request using fetch()
https://googlechrome.github.io/samples/fetch-api/fetch-post.html
for more details about fetch API see :
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
or this thread :
Fetch: POST JSON data

ffmpeg app using node occasionally crashes as file doesn't appear to be read correctly

I have an simple Node application that allows me to pass an AWS S3 URL link to a file (in this case video files). It uses the FFMPEG library to read the video file and return data like codecs, duration, bitrate etc..
The script is called from PHP script which in turn send the data to the Node endpoint and passes the Amazon S3 URL to node. Sometimes for no obvious reasons the video file fails to return the expected values regarding container, codec, duration etc... and just returns '0'. But when I try the exact same file/request again it returns this data correctly e.g container:mp4
I'm not sure but I think the script somehow needs the createWriteStream to be closed but I cannot be sure, the problem is the issue I have found doesn't happen all the time but sporadically so its hard to get to the issue when its difficult to replicate it.
Any ideas?
router.post('/', async function(req, res) {
const fileURL = new URL(req.body.file);
var path = fileURL.pathname;
path = 'tmp/'+path.substring(1); // removes the initial / from the path
let file = fs.createWriteStream(path); // create the file locally
const request = https.get(fileURL, function(response) {
response.pipe(file);
});
// after file has saved
file.on('finish', function () {
var process = new ffmpeg(path);
process.then(function (video) {
let metadata = formatMetadata(video.metadata);
res.send ({
status: '200',
data: metadata,
errors: errors,
response: 'success'
});
}, function (err) {
console.warn('Error: ' + err);
res.send ({
status: '400',
data: 'Something went wrong processing this video',
response: 'fail',
});
});
});
file.on('error', function (err) {
console.warn(err);
});
});
function formatMetadata(metadata) {
const data = {
'video' : metadata.video,
'audio' : metadata.audio,
'duration' : metadata.duration
};
return data;
}
// Expected output
{"data":{"video":{"container":"mov","bitrate":400,"stream":0,"codec":"h264","resolution":{"w":1280,"h":720},"resolutionSquare":{"w":1280,"h":720},"aspect":{"x":16,"y":9,"string":"16:9","value":1.7777777777777777},"rotate":0,"fps":25,"pixelString":"1:1","pixel":1},"audio":{"codec":"aac","bitrate":"127","sample_rate":44100,"stream":0,"channels":{"raw":"stereo","value":2}},"duration":{"raw":"00:00:25.68","seconds":25}}
// Actual output
{"data":{"video":{"container":"","bitrate":0,"stream":0,"codec":"","resolution":{"w":0,"h":0},"resolutionSquare":{"w":0,"h":null},"aspect":{},"rotate":0,"fps":0,"pixelString":"","pixel":0},"audio":{"codec":"","bitrate":"","sample_rate":0,"stream":0,"channels":{"raw":"","value":""}},"duration":{"raw":"","seconds":0}}
Note - this happens sporadically
You are not accounting for a failed fetch from AWS. You should check the status code of the response before you move on to your pipe.
const request = https.get(fileURL, function(response) {
if(response.statusCode == 200)
response.pipe(file);
else
// Handle error case
});

How to download a file with Node.js from google drive api

How to download a file with Node.js from google drive api
I don't need anything special. I only want to download a file from a GoogleDrive, and then save it to a given directory of client.
app.get("/download",function(req,res){
const p38290token = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);
p38290token.setCredentials({ refresh_token: token.acc });
const p38290Id = google.drive({
version: "v3",
auth: p38290token,
});
var dest = fs.createWriteStream("./test.png");
try {
p38290Id.files.get({
fileId: "1daaxy0ymKbMro-e-JnexmGvM4WzW-3Hn",
alt: "media"
}, { responseType: "stream" },
(err, res) => {
res.data
.on("end", () => {
console.log("Done");
})
.on("error", err => {
console.log("Error", err);
})
.pipe(dest); // i want to sent this file to client who request to "/download"
}
)
} catch (error) {
}
})
I want to do that just someone come to www.xyz.com/download and file will be download automatically
The issue seems to be with this line:
var dest = fs.createWriteStream("./test.png");
You are using a file system command which is meant to interact with files on the server. Your question makes it clear that you wish for express to deliver the contents of the file over to the client making the HTTP request.
For that you can just use the res parameter of the route callback function. You declare it on this line:
app.get("/download",function(req,res){
In your case I'd remove the dest variable completely and simply pipe the file to res like so:
.pipe(dest);
Have a look at this answer as well.

Receive and Send Attachment as Email within Microsoft Bot Framework

I am currently building a chatbot that is able to receive attachments and save them to a local directory.
I want to find out how to use that same attachment and send it via email.
async downloadAttachmentAndWrite(attachment) {
// Retrieve the attachment via the attachment's contentUrl.
const url = attachment.contentUrl;
console.log(attachment)
// Local file path for the bot to save the attachment.
const localFileName = path.join(__dirname, attachment.name);
try {
// arraybuffer is necessary for images
const response = await axios.get(url, { responseType: 'arraybuffer' });
console.log('#####')
console.log(response.data)
// If user uploads JSON file, this prevents it from being written as "{"type":"Buffer","data":[123,13,10,32,32,34,108..."
if (response.headers['content-type'] === 'application/json') {
response.data = JSON.parse(response.data, (key, value) => {
return value && value.type === 'Buffer' ? Buffer.from(value.data) : value;
});
}
fs.writeFile(localFileName, response.data, (fsError) => {
console.log(localFileName)
console.log(response.data)
if (fsError) {
throw fsError;
}
});
} catch (error) {
console.error(error);
return undefined;
}
// If no error was thrown while writing to disk, return the attachment's name
// and localFilePath for the response back to the user.
return {
fileName: attachment.name,
localPath: localFileName
};
}
That is currently the function to receive and save to directory, but how do I actually capture the attachment and send it to another function?
Look over the 24.bot-authentication-msgraph sample in the BotBuilder-Samples repo. This sample demonstrates how a bot can be setup to send an email on the user's behalf.
Using that sample as a reference/template, you can infer how this process could work for you (in case you are not using MS Graph). The docs here explain how a file can be included as an attachment in an email.
If you preserve the location of the saved file, you should be able to read the file from the local directory and, using the method referenced above, attach the file before sending.
Hope of help.

Retrieving multipart form data from a mongodb gridfs database and displaying image in react native app

Please I need help, I have been stuck on this problem for the past two weeks. I am uploading text data along with images using multer and gridfs to mongodb database and the upload works fine as the data is uploaded and stored in different chunks. However I am trying to accomplish two things:
Retrieve the data stored alongside the image
Get the image data and display it in my react native app
My database looks like this:
The data text data is in the post collection, while the image data is in the image_uploads.chunks and image_upload.files which are all uploaded via the same post route using multipart form data, multer and gridfs.
This is the server side get route where I am retrieving data from mongodb and serving the client side.
/////////////////////////////Media Download Route//////////////////////
router.get('/post', async (req, res) => {
gfs.files.find().toArray((err, files) => {
// Check if files
if (!files || files.length === 0) {
res.send({ files: false });
} else {
files.map(file => {
if (
file.contentType === 'image/jpeg' ||
file.contentType === 'image/png'
) {
file.isImage = true;
} else {
file.isImage = false;
}
});
res.send({ files: files});
}
});
});
Below is the client side code, that receives the data from the server.
const [photo, setPhoto] = useState(null)
const getPost = async () => {
try {
const response = await dataApi.get('/post');
const image = response.data.files[0].filename
console.log(response.data)
console.log('Image: ', image)
console.log('Data: ', response.body)
setPhoto(image)
} catch (err) {
console.log(err.message)
}
}
console.log('Photo: ', photo)
Below is the std out of the response.data, this is the data in image_uploads.files, the goal will be to display all the images in image_uploads.files. However, I am taking just the first image filename (ie 2157d425c51a5f3f5a7cf8579137eeb6.jpg) to test and calling setPhoto to set photo state to it. But when I assign it to an image tag the display is blank in the app, I suspect the file name should be attached with something maybe the url to database not sure please help.
The second problem is for every image in image_uploads.files, I want to retrieve its associated data in the post collection which were uploaded along with the image using multipart form data. The post.mediaData.id in post collection is a foreign key which is the image id, but the response.body or response does not have the data in post collection please help. Thanks in advance
Object {
"files": Array [
Object {
"_id": "5de29f8dd0f99e6d6a0371ef",
"chunkSize": 261120,
"contentType": "image/jpeg",
"filename": "2157d425c51a5f3f5a7cf8579137eeb6.jpg",
"isImage": true,
"length": 1046594,
"md5": "7e1cb512a36b901e3acfcb9d08f0778f",
"uploadDate": "2019-11-30T16:57:52.372Z",
},
Object {
"_id": "5de2c1bed0f99e6d6a0371f6",
"chunkSize": 261120,
"contentType": "image/jpeg",
"filename": "3ffe7616d7956084219cb4f134c89798.jpg",
"isImage": true,
"length": 1046594,
"md5": "7e1cb512a36b901e3acfcb9d08f0778f",
"uploadDate": "2019-11-30T19:23:45.053Z",
},
],
}
Image: 2157d425c51a5f3f5a7cf8579137eeb6.jpg
Data: undefined
Photo: 2157d425c51a5f3f5a7cf8579137eeb6.jpg

Categories