Ohad Cohen
Ohad Cohen

Reputation: 6144

Use GM_xmlhttpRequest to POST data on Chrome?

I'm writing a user script to take an image from a page, and upload it to a server. The script works fine in FF (Greasemonkey and Scriptish), but when I use Chrome (using Tampermonkey or Ninjakit), it does not send the data, it sends the string * [object Object] * instead.

Here is my script:

// ==UserScript==
// @id             myid
// @name           myname
// @version        1.0
// @namespace      ohadcn
// @author         Ohad Cohen
// @description    mydescription
// @include        https://*
// @grant          GM_xmlhttpRequest
// @require        https://code.jquery.com/jquery-2.0.3.min.js
// @run-at         document-end
// ==/UserScript==

function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
    var dataURL = canvas.toDataURL("image/png");
    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

img=$("img[alt=myImage]").get(0);

img.onload=function(){
    var img64=getBase64Image(img)
    var _data=new FormData();
    _data.append("image64",img64);

    GM_xmlhttpRequest({
    method: "POST",
    url: "http://myserver.org/mysscript.py",
    headers: {
    "Content-Type": "multipart/form-data"
    },
    data:_data,
    onload: function(response) {
             console.log ("gut response");
         $("#input").get()[0].value=response.responseText;
    }
    });
}


Both Tampermonkey and Ninjakit do send the request. In Tampermonkey, I get a response, in Ninjakit I don't (onload is never called).

But they do not send the actual image encoded with base64 - when I read the data - the server gets [object Object] as the POST body (Instead of data body, I can't get devtools network panel to show requests made by GM_xmlhttpRequest, so I checked it on the server side).

Upvotes: 6

Views: 22075

Answers (2)

Juribiyan
Juribiyan

Reputation: 740

You can do it at least in Tampermonkey by setting the fetch parameter to true. This way when you pass an instance of FormData as data parameter it will just work. Not sure if other userscript managers support using fetch instead of XMLHttpRequest but Greasemonkey supports FormData in the data field anyways.

    let fd = new FormData()
    fd.append('field_name', 'field_value')
    fd.append('file_upload', file) // an instance of File
    
    GM.xmlHttpRequest({
      method: "POST",
      url: "https://upload.api",
      onload: function(res) {
        // ...
      },
      onerror: function(e) {
        // ...
      },
      data: fd,
      fetch: true
    })

Upvotes: 0

Brock Adams
Brock Adams

Reputation: 93473

It might be that FormData and multipart/form-data are not well supported on those platforms. Need to look into it more (later).

Meanwhile, try the more typical approach; use application/x-www-form-urlencoded or JSON.

EG:

GM_xmlhttpRequest ( {
    method:     "POST",
    url:        "http://myserver.org/mysscript.py",
    data:       "image64=" + encodeURIComponent (img64),
    headers:    {
        "Content-Type": "application/x-www-form-urlencoded"
    },
    onload:     function (response) {
        console.log ("gut response");
        $("#input").get()[0].value=response.responseText;
    }
} );

Upvotes: 7

Related Questions