smalltalk - Send a file over websocket with pharo, ZnWebsocket, and Fuel in Pharo 2.0? -
i trying send large video files on websocket using pharo 2.0, , zinc websocket. pharo pharo transfer.
i have tried in vain work. i'm sure there's simple solution i'm missing. help.
edit: update: did work, through following code:
mystream := (filestream oldfilenamed: 'big_buck_bunny_480p_surround-fix.avi') . bytes := mystream next: mystream size. mystream close. mystream := nil. server distributemessage: bytes. testconnect | websocket1 receivedfile| websocket1 := znwebsocket to: 'ws://192.168.1.102:1701/ws-chatroom'. testprocess := [ [ | mes | mes := [ websocket1 readmessage ] on: connectiontimedout do: [ nil ]. mes ifnotnil: [ transcript show: 'message received in client';cr . receivedfile := filestream newfilenamed: 'receivedfile3.avi'. receivedfile nextputall: mes. receivedfile close. ] ] repeat ] fork
however, doesn't work files bigger ~500 megabytes, because pharo runs out of memory.
unless has great suggestion work, i'm going switch gears , try serve files using zinchttpcomponents, , perhaps send message remote computer containing location of file download on webserver.
edit: important warning/update:
i discussed issue sven wrote zinc websocket packages pharo smalltalk. told me sending large files on websocket not feasible idea. indeed, though got solutions below implemented, final file off few bytes every time.
i solved issue doing plan b: serving files on http using zinc http components , using client such as:
filestream newfilenamed: '/tmp/cog.tgz' do: [ :stream | | entity | stream binary. entity := znclient new streaming: true; get: 'https://ci.lille.inria.fr/pharo/job/cog%20git%20tracker/lastsuccessfulbuild/artifact/cog.tar.gz'; entity. entity writeon: filestream ]
the reason you're running out of memory read entire file memory before processing it. since can send chunks of data on wire anyway, should read 1 chunk @ time (that's streams for). instead of this:
mystream := (filestream oldfilenamed: 'big_buck_bunny_480p_surround-fix.avi'). bytes := mystream next: mystream size. mystream close.
you should use this:
blocksize := 128. mystream := (filestream oldfilenamed: 'big_buck_bunny_480p_surround-fix.avi') . [ mystream atend ] whilefalse: [ bytes := mystream next: blocksize. "process bytes here" ]. mystream close.
or better: use convenience block automatically close stream:
blocksize := 128. filestream oldfilenamed: 'big_buck_bunny_480p_surround-fix.avi' do: [ :stream | [ stream atend ] whilefalse: [ bytes := stream next: blocksize. "process bytes here" ].
edit
to answer question comment: if @ filestream>>next:
see following lines:
... [self atend iftrue: [(howmanyread + 1) to: aninteger do: [:i | newcollection at: put: (self next)]. ^newcollection]. ...
this means if ask more available, rest of stream end.
Comments
Post a Comment