Reputation: 2304
I am running a clojurescript (cljs) browser repl and I want to be able to write some text to a local file.
I tried the following:
(spit "abc.txt" "hello")
but this returns:
#<TypeError: Cannot read property 'call' of undefined>
TypeError: Cannot read property 'call' of undefined
Under a clojure repl this will create file "abc.txt" in the root dir of my project.
I realize that 'spit is a clojure function, but I wonder if there is also some easy way to do this in cljs?
Or is this strictly a JavaScript question and not relevant to clojurescript proper?
Upvotes: 2
Views: 2826
Reputation: 2304
node.js example.
Less hassle than writing a cgi. New to node.js, so just a starter. Did not convert to cljs.
// to run:
// node write_file.js
// to call from cmd line:
// curl localhost:9090?fn=test.txt\&msg=hello%20world
var http = require('http');
var fs = require('fs');
var url = require('url');
var server = http.createServer(function(req, res) {
var fn = url.parse(req.url, true).query['fn'];
var msg = url.parse(req.url, true).query['msg'];
fs.writeFile(process.env.HOME + "/vtstuff/tmp/" + fn, msg + "\n",
function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
console.log("fn=" + fn);
console.log("msg=" + msg);
process.argv.forEach(function (val, index, array) {
console.log(index + ': ' + val);
});
});
res.writeHead(200,{"Content-Type": "text/plain"});
res.end("wrote file\n");
});
server.listen(9090);
Upvotes: 0
Reputation: 2304
I am posting this as an example solution, and I am not saying this is how you should do it. I did experience a few "gotchas" however, so I think it's worthwhile to document.
Thank you for your answer. I was just trying to find out if there was some easier way before doing what I knew I would have to do otherwise. I decided to go with a server-side write.
I am using cider, chestnut, and a brepl server interfacing with a chrome client. Since I am not familiar with ring servers, compojure, and embedded jetty servers, I did not know how to add a web service to the brepl server (port 10555). Instead I added one to my local apache server.
Because the request comes in to apache from the the jetty server (as opposed to from a browser), I was getting "cross origin resource sharing" issues, namely message:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
whenever I submitted a request to my service's URL.
I was able to get around this issue by adding the following to my http headers:
-access_control_allow_credentials => 'true',
-access_control_allow_origin => 'http://localhost:10555',
That was about the only gotcha. Beyond that, it's a standard cgi solution (yeah, old school -- I come from a perl background). And yes, I know it would have been best if I could have done it in clojure (or Rails).
My cgi ended up looking something like:
#!/usr/bin/perl
use CGI qw(:standard);
print header(
-type => 'text/html',
-access_control_allow_credentials => 'true',
-access_control_allow_origin => 'http://localhost:10555',
);
my $q = CGI->new();
my $src = $q->param('src');
# write to file
open(my $fh, ">>", "vt-src-out.txt")
or die "cannot open < vt-src-out.txt: $!";
print $fh "$src\n";
I used ajax.core as my client api:
:require [ajax.core :refer [GET POST]]
and called the service like:
(GET "http://localhost/cgi-bin/cljs-write-src.cgi" {:params {:src "(defn foo [])(+ 1 1)"}})
Upvotes: 0
Reputation: 618
From a browser I think you can't (like in JS), because security.
From nodejs check the nodejs doc :)
Now if you mix in a little bit of flash (yuk :|...) there's a JS library for that (that you can use in cljs).
https://github.com/dcneiner/Downloadify
Upvotes: 4