Node Js Meme generation error: File does not exist - javascript

Total nodejs newbie here. I am using meme-maker package to generate meme. However I want to create meme with image from url
var fileName = 'https://imgflip.com/s/meme/Futurama-Fry.jpg';
var memeMaker = require('meme-maker')
var options = {
image: fileName, // Required
outfile: 'meme.png', // Required
topText: 'top', // Required
bottomText: 'bottom', // Optional
}
memeMaker(options, function(err) {
if(err) throw new Error(err)
console.log('Image saved: ')
});
However I get error: Error: File does not exist: https://imgflip.com/s/meme/Futurama-Fry.jpg
How to read file from url and make meme?

If you go read the documentation of meme-maker you will see that it only supports local images and not URL's.
You will need to download the image first then use the local address. Go have a look at request

That library does not look like it supports URLs. The image param presumably takes a file path on the local system. If you want to use the URL to make a meme, you will have to:
Download that image from the URL using AJAX or something similar, store it to a file on the disk and get it's local path.
Pass the local file path of the file to the library
Get the generated meme path (and enable download if needed) and do clean up like deleting the old image, for example

Related

Is there a way to download any kind of file using angular filesaver?

I'm using node.js and angular.js for my app and I'm trying to download files through the browser using Blob and fileSaver.js.
I've used these in other sections of my app to download text files and pdf files specifying the correct type when creating the Blob object without any problem, but in the current section I need to support any type of file and I don't know if it's possible.
For example, I've tried downloading an image file with and without type:image/png and the result was a corrupted image - inspecting it in a text editor and comparing it with the original file shows that many of the bytes were changed.
Here are the code snippets I use:
Server:
fs.readFile(/* snipped file path */, function(err, data){
if(err){
/* handle error */
}
else{
res.send(data);
}
});
Client:
$http.get(/* endPoint URL */)
.success(function(result){
var data = new Blob([result], {type: 'image/png'});
FileSaver.saveAs(data, filename);
});
A few questions:
Do I need to specify type for Blob? If so, do I need to specify it at server, too (it's a pain to determine it)? Can't I just skip it on both ends?
What causes the image test to result in corrupted file? Am I missing some content-type header or something?
Try adding {contentType: 'arraybuffer'} to your GET request and remove type from Blob definition, like so:
$http.get(/* endPoint URL */, {contentType: 'arraybuffer'})
.success(function(result){
var data = new Blob([result]);
FileSaver.saveAs(data, filename);
});
(Edit: deleted redundant type definition from Blob)

How to serve static files in node.js after renaming them?

I am creating a node.js app in which user can upload files and can download later.
I am storing file information (original file name that user uploaded, ...) in mongodb document and named that file same as mongodb document id. Now i want my user to be able to download that file with the original file name.
What i want to know is when a user sends a GET request on http://myapp.com/mongoDocument_Id
user gets a file named myOriginalfile.ext
I know about node-static and other modules but i can't rename them before sending file.
i am using koa.js framework.
Here's a simple example using koa-file-server:
var app = require('koa')();
var route = require('koa-route');
var send = require('koa-file-server')({ root : './static' }).send;
app.use(route.get('/:id', function *(id) {
// TODO: perform lookup from id to filename here.
// We'll use a hardcoded filename as an example.
var filename = 'test.txt';
// Set the looked-up filename as the download name.
this.attachment(filename);
// Send the file.
yield send(this, id);
}));
app.listen(3012);
In short:
the files are stored in ./static using the MongoDB id as their filename
a user requests http://myapp.com/123456
you look up that ID in MongoDB to find out the original filename (in the example above, the filename is just hardcoded to test.txt)
the file ./static/123456 is offered as a download using the original filename set in the Content-Disposition header (by using this.attachment(filename)), which will make the browser store it locally as test.txt instead of 123456.

Download files from server using Meteor.js

Here is my workflow as of now:
In a button click event, I have search results being exported to a .csv file, which is saved to the server. Once the file is saved, I want to send it for download to the browser. Using this question How to handle conditional file downloads in meteor.js, I created a method that is called after the method that saves the file returns. Here is that method:
exportFiles: function(file_to_export) {
console.log("to export = "+file_to_export);
Meteor.Router.add('/export', 'GET', function() {
console.log('send '+file_to_export+' to browser');
return [200,
{
'Content-type': 'text/plain',
'Content-Disposition': "attachment; filename=" + this.request.query.file
}, fs.readFileSync( save_path + this.request.query.file )];
});
}
My question, however, is how to invoke that route? Using .Router.to('/export?file=filename.ext') doesn't work, and causes the user to leave the current page. I want this to appear seamless to the user, and I don't want them to have any idea they are being redirected. Before anyone asks, save_path is declared outside of the method, so it does exist.
I have gotten it! However, it required the use of a few additional packages. First, let me describe the workflow a little more clearly:
A user on our site performs a search. On the subsequent search results page, a button exists that allows the user to export his/her search results to a .csv file. The file is then to be exported to the browser for download.
One concern we had was if a file is written to the server, making sure only the user who is exporting the file has the ability to view the file. To control who had visibility on files, I used a meteorite package, CollectionFS (mrt add collectionFS or clone from github). This package writes file buffers to a mongo collection. Supplying an "owner" field when saving gives you control over access.
Regardless of how the file is created, whether saved to the server via an upload form or generated on the fly the way I did using the json2csv package, the file must be streamed to CollectionFS as a buffer.
var userId = Meteor.userId()
var buffer = Buffer(csv.length); //csv is a var holding the data for write
var filename = "name_of_file.csv";
for ( var i=0; i<csv.length; i++ ) {
buffer[i] = csv.charCodeAt(i);
}
CollectionFS.storeBuffer(filename, buffer, {
contentType: 'text/plain',
owner: userId
});
So at this point, I have taken my data file, and streamed it as a buffer into the mongo collection. Because my data exists in memory in the var csv, I stream it as a buffer by looping through each character. If this were a file saved on a physical disk, I would use fs.readFileSync(file) and send the returned buffer to CollectionFS.storeBuffer().
Now that the file is saved as a buffer in mongo with an owner, I can limit through way I publish the CollectionFS collection who can download/update/delete the file or even know the file exists.
In order to read the file from mongo and send the file to the browser for download, another Javascript library is necessary: FileSaver (github).
Using the retrieveBlob method from CollectionFS, pull your file out of mongo as a blob by supplying the _id that references the file in your mongo collection. FileSaver has a method, saveAs that accepts a blob, and exports to the browser for download as a specified file name.
var file = // file object stored in meteor
CollectionFS.retrieveBlob(file._id, function(fileItem) {
if ( fileItem.blob ) saveAs(fileItem.blob, file.filename);
else if ( fileItem.file ) saveAs(fileItem.file, file.filename);
});
I hope someone will find this useful!
If your route works, when when your method returns you could open a new window containing the link to the text file.
You've already added in content disposition headers so the file should always ask to be saved.
Even if you just redirect to the file, because it has these content disposition headers it will ask to be saved and not interrupt your session.

HTML5: drag out a JS generated file

I have a feeling security concerns may not allow this but is it possible to generate a file with JavaScript and allow the user to drag it to the desktop (or file system)?
The following code drags out a file from a server
files[0].addEventListener("dragstart",function(evt){
evt.dataTransfer.setData("DownloadURL", "application/octet-stream:Eadui2.ttf:http://thecssninja.come/demo/gmail_dragout/Eadui.ttf");
},false);
And with the below code I can generate a file and have it download but I can't set the file name or let the user select the location.
var uriContent = "data:application/octet-stream," + encodeURIComponent(JSON.stringify(map));
location.href = uriContent;
Ideally I'd like a magical combination of both.
following code is currently working in Chrome only:
// generate downloadable URL, file name here will not affect stored file
var url = URL.createObjectURL(new File([JSON.stringify(map)], 'file_name.txt'));
// note that any draggable element may be used instead of files[0]
// since JSON.stringify returns a string, we use 'text' type in setData
files[0].addEventListener("dragstart", function(evt) {
evt.dataTransfer.setData("DownloadURL", "text:file_name.txt:" + url);
}, false);
now, dragging our files[0] element from the browser to desktop or file system, will store there a text file called, file_name.txt.
Feel free to choose another file name :)
This is only possible for Chrome, and even in Chrome you can't set the location. If using only Chrome is okay then you will have the following options:
Stick with Drag n' Drop like from the CSS Ninja's tutorial, then you should try Ben's answer. encodeURIComponent is one way, but if you have the file generated using BlobBuilder then you can use window.webkitURL.createObjectURL() to get the file's URL. You can also try using FileWriter() with requestFileSystem(TEMPORARY, ...).
Chrome supports download attribute for anchor tags so you can have regular link for the user to click (dragging also works):
Download
For cross browser support I suggest Downloadify.
You could try sending it to the server, saving the file, checking the return value and firing the download file function, followed by a server file that deletes the file from the server.
Something like this (with jQuery)
$.ajax({
url: 'saveFile.php',
method: 'post',
data: {
Filedata: data// file data variable
},
success: function(d) {
// save file function, where d is the filename
}
})
PHP:
$filename = ;//generate filename
file_put_contents($filename, $_POST['Filedata']);
echo $filename;
Obviously there is more to it but that should be the basics

Reading image capture files in PhoneGap

I'm working on a PhoneGap application that captures images using the camera and, later, uploads them. There are two modes of operation for camera in PhoneGap: raw base64 encoded data or a file URI.
The docs themselves say:
Note: The image quality of pictures taken using the camera on newer
devices is quite good. Encoding such images using Base64 has caused
memory issues on some of these devices (iPhone 4, BlackBerry Torch
9800). Therefore, using FILE_URI as the 'Camera.destinationType' is
highly recommended.
So I'm keen to use FILE_URI option. This works great and you can even show the images in IMG tags. The URL looks like this:
file://localhost/var/mobile/Applications/4FE4642B-944C-449BB-9BD6-1E442E47C7CE/tmp/photo_047.jpg
However, at some point later I want to read the contents of the file to upload to a server. I was going to do this using the FileReader type. This doesn't work and I think it's because I can't access the file at the URL above.
The error code I get back from readDataUrl is 1 > FileError.NOT_FOUND_ERR = 1;
Any ideas how I can get to the file? I tried just accessing the last part of the path (photo_047.jpg) based on another sample I saw but no luck.
I'm just getting started with PhoneGap, and given the age of this question you may have found an answer already, but I'll give it a try anyway.
First, would you be able to use the built-in FileTransfer object? It takes a file: URI as an argument.
If FileTransfer won't work for you, and you need to read the file data yourself, you'll need the PhoneGap File objects, like FileReader , as you said. But most of those expect a plain pathname -- not a URI -- to specify the file to work with. The reason you're getting NOT_FOUND_ERR is because it's trying to open a file named file:/localhost/var....
Here's a quick one-liner to extract the path part from your URI:
var path = /file:\/\/.*?(\/.*)/.exec(fileuri)[1];
Hope this helps!
The answer from jgarbers was of help to me but it did not solve the problem. I realized the camera stores photos in Temp folder instead of Document folder. Setting my local file system to temporary allowed it to find the correct location for the camera images.
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, ...
...
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, ...
...
var path = /file://.?(/.)/.exec(fileuri)[1];
Ref. above jgarbers and Rik answers (solution has been tested successfully on iOs 7)
you can user the file transfer plugin for uploading any file to the server.
//// pass your file uri to the mediafie param
function uploadFile(mediaFile) {
var ft = new FileTransfer();
path = mediaFile.fullPath;
name = mediaFile.name;
////your service method url
var objUrl = http://example.com;
ft.upload(path,
objUrl,
function (result) {
alert("Success");
},
function (error) {
alert('Error uploading file ' + path + ': ' + error.code);
},
{ fileName: name });
}

Categories