UPDATE 1: I've created a GIST with actual running code in a test jig to show exactly what I'm running up against. I've included working bot tokens (to a throw-away bot) and access to a telegram chat that the bot is already in, in case anyone wants to take a quick peek. It's
https://gist.github.com/pleasantone/59efe5f9d7f0bf1259afa0c1ae5a05fe
UPDATE 2: I've looked at the following articles for answers already (and a ton more):
https://github.com/francois2metz/html5-formdata/blob/master/formdata.js
PhantomJS - Upload a file without submitting a form
https://groups.google.com/forum/#!topic/casperjs/CHq3ZndjV0k
How to instantiate a File object in JavaScript?
How to create a File object from binary data in JavaScript
I've got a program written in casperjs (phantomjs) that successfully sends messages to Telegram via the BOT API, but I'm pulling my hair out trying to figure out how to send up a photo.
I can access my photo either as a file, off the local filesystem, or I've already got it as a base64 encoded string (it's a casper screen capture).
I know my photo is good, because I can post it via CURL using:
curl -X POST "https://api.telegram.org/bot<token>/sendPhoto" -F chat_id=<id> -F photo=@/tmp/photo.png
I know my code for connecting to the bot api from within capserjs is working, as I can do a sendMessage, just not a sendPhoto.
function sendMultipartResponse(url, params) {
    var boundary = '-------------------' + Math.floor(Math.random() * Math.pow(10, 8));
    var content = [];
    for (var index in params) {
        content.push('--' + boundary + '\r\n');
        var mimeHeader = 'Content-Disposition: form-data; name="' + index + '";';
        if (params[index].filename)
            mimeHeader += ' filename="' + params[index].filename + '";';
        content.push(mimeHeader + '\r\n');
        if (params[index].type)
            content.push('Content-Type: ' + params[index].type + '\r\n');
        var data = params[index].content || params[index];
//        if (data.length !== undefined)
//            content.push('Content-Length: ' + data.length + '\r\n');
        content.push('' + '\r\n');
        content.push(data + '\r\n');
    };
    content.push('--' + boundary + '--' + '\r\n');
    utils.dump(content);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", url, false);
    if (true) {
        /*
         * Heck, try making the whole thing a Blob to avoid string conversions
         */
        body = new Blob(content, {type: "multipart/form-data; boundary=" + boundary});
        utils.dump(body);
    } else {
        /*
         * this didn't work either, but both work perfectly for sendMessage
         */
        body = content.join('');
        xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
//        xhr.setRequestHeader("Content-Length", body.length);
    }
    xhr.send(body);
    casper.log(xhr.responseText, 'error');
};
Again, this is in a CASPERJS environment, not a nodejs environment, so I don't have things like fs.createReadableStream or the File() constructor.
 
    