简体   繁体   中英

With gjs, how can I write Soup.Buffer chunks of data to a file?

I'm writing a GTK javascript program that downloads a file and writes it to disk. Here's what my code looks like:

const Gio = imports.gi.Gio;
const Soup = imports.gi.Soup;

// start an http session to make http requests
let _httpSession = new Soup.SessionAsync();
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());

// open the file
let file = Gio.file_new_for_path(path);
let fstream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);

// start the download
let request = Soup.Message.new('GET', url);
request.connect('got_chunk', Lang.bind(this, function(message, chunk){
  // write each chunk to file
  fstream.write(chunk, chunk.length, null);
}));

this._httpSession.queue_message(request, function(_httpSession, message) {
  // close the file
  fstream.close(null);
});

I get an error on the fstream.write() line:

    JS ERROR: !!!   Exception was: Error: Unhandled GType GCancellable unpacking GArgument from Number
    JS ERROR: !!!     message = '"Unhandled GType GCancellable unpacking GArgument from Number"'
    JS ERROR: !!!     fileName = '"./torbrowser-launcher"'
    JS ERROR: !!!     lineNumber = '402'
    JS ERROR: !!!     stack = '"([object _private_Soup_Message],[object _private_Soup_Buffer])@./torbrowser-launcher:402
("2.3.25-2")@./torbrowser-launcher:122
wrapper("2.3.25-2")@/usr/share/gjs-1.0/lang.js:204
("2.3.25-2")@/usr/share/gjs-1.0/lang.js:145
("2.3.25-2")@/usr/share/gjs-1.0/lang.js:239
@./torbrowser-launcher:489
"'

The only reference to this error that I can find is in this thread: https://mail.gnome.org/archives/gnome-shell-list/2012-July/msg00126.html

That person ended up giving up and porting his code to python.

I'm also confused by what the 'got_chunk' callback passes. The chunk field is a Soup.Buffer ( http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Soup.Buffer.html ). I can get its length with chunk.length, but when I try printing chunk.data it's undefined. When I just print chunk it prints: [object _private_Soup_Buffer].

fstream is a Gio.FileOutputStream ( http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Gio.FileOutputStream.html ). The write method is: write(String buffer, guint32 count, Cancellable cancellable), and cancellable is optional. Weirdly enough, if I replace the write line with this I still get the exact same error:

fstream.write('test ', 5, null);

I was hitting exactly the same problem. After a lot of trial and error, it boiled down to two issues with the write() call:

  1. It seems that the documentation of the write function you are using ( http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Gio.FileOutputStream.html ) is wrong; the write method signature is (as far as I can tell):

    write(String buffer, Cancellable cancellable, guint32 count)

  2. Yet if you just use fstream.write(chunk, null, chunk.length); you will write a file full of zeros. I don't know why (something to do with the way GJS binds to the underlying C library) but you should use chunk.get_data() instead of just chunk . Ie replace the write call in your code with:

    fstream.write(chunk.get_data(), null, chunk.length);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM