Closer to bypassing Flex print dialogue?
I know this is a pretty heavy topic and see requests for it all the time (I believe the stance for blocking it is security related).
While messing around trying to get ZPL printing working in AIR, I ran into something interesting.
Looking at other programming languages and their attempts to print to ZPL, most of them handle it through a File Stream and treat the printer as a file (see here for a .NET example .NET code to send ZPL to Zebra printers).
I took this approach with Flex and got some interesting results.
I tested this talking directly to a network shared printer on my own PC. It's a simple piece of code:
var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
Obviously you will need to fill in your own info for PC-Name (network name) and Printer-Name (printer's shared name).
If you watch your printer, you'll notice that it does initiate spooling with this request.
Unfortunately, this is about as far as I'm able to get with it. Initiating any sort of actually writing over that stream doesn't seem to work (although I'm far from an expert on the matter, I could be missing something).
Stepping through something like:
var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.close();
You can watch it hit the spooler with the open and then successfully close without any ill effects.
Once you add an actual write though such as:
var byteArray:ByteArray = new ByteArray();
byteArray.writeUTFBytes("Hello World");
byteArray.position = 0;
var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeBytes(byteArray, 0, byteArray.length);
stream.close();
It all goes to hell unfortunately.
Some things to note about the variables and what happens:
After declaring your file (var file:File = new File('\\PC-Name\Printer-Name');), when you inspect the file variable you'll notice a few issues. creationDate, modificationDate, and size all have "exception thrown by getter" errors. More specifically "Error: Error #3003: File or directory does not exist.". I'm not overly concerned with these as it isn't a file, it's a printer.
After opening the stream (stream.open(file, FileMode.WRITE);) and inspecting the stream variable the "bytesAvailable" has an "exception thrown by getter" (Error: Error #2029: This URLStream object does not have a stream opened). Once again, it isn't a file so the bytesAvailable like this might be okay (or it may be the reason everything after this seems to fail). At this point, you will also have a print document with a status of "Spooling" in your print queue.
Calling stream.writeBytes(byteArray, 0, byteArray.length); causes the stream variable position to move from 0 to 167 (the length of my byteArray). So it seems to think it attempts to write. Nothing "bad" seems to happen here.....
Calling stream.close(); however, brings the whole thing crashing down with a "Error #2038: File I/O Error. at flash.filesystem::FileStream/close()
Posting this here to see if anyone has any ideas (am I missing something? Is it completely not possible? Close but no cigar?)
******** UPDATE *********
I did find a way to accomplish this with a network printer (unfortunately not with a windows shared printer). It is using sockets instead of filestreams. I can almost guarantee you this will throw some sandbox violations upon an actual release so that will need to be handled (socket policy files I would assume).
public var socket:Socket = new Socket();
socket.addEventListener( Event.CONNECT, onConnect);
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData);
socket.connect(ip_address, 9100);
private function onConnect(event : Event) : void {
var byteArray:ByteArray = new ByteArray();
byteArray.writeUTFBytes("Hello World");
byteArray.position = 0;
socket开发者_StackOverflow社区.writeBytes(byteArray, 0, byteArray.length);
socket.removeEventListener(Event.CONNECT, onConnect);
socket.removeEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
socket.flush();
socket.close();
}
public function onSocketData(event:Event):void {
trace("onSocketData Fired");
}
Not sure if one can even connect over a socket to a windows shared printer (ie a printer connected to someone's PC and shared). So far I haven't had any luck. But, if you are strictly dealing with networked printers this might work for you to skip/bypass the flex print dialogue.
I'm making a few assumptions: If you're using AIR and you have a working .Net solution and you are targeting Windows only... why not just use the .Net solution and call it using NativeProcess
class?
Basically you compile the ZPL .NET printer as an EXE and call it using NativeProcess, passing in the printer string.
That way you can still have a nice Flexy interface but get native printing controls.
精彩评论