2

I have a flex program (AS3/Flash) that allows the user to create PNG images of portions of the stage and send them via email. This works swimmingly.

I want to take the same image and send it to the clipboard, but that does not work. So the next best thing is to allow them to send it to their browser, where they can save it to a file.

Here is the code that I am using to do that;

            bmpPanelData.draw(uiPrintObject)
        var baPanel:ByteArray = PNGEnc.encode(bmpPanelData);
//      Clipboard.generalClipboard.clear();
//      var bolClipboard:Boolean = Clipboard.generalClipboard.setData(ClipboardFormats.BITMAP_FORMAT, baPanel, true);
//      trace('bolClipboard=' + bolClipboard);

            var strFileName:String = strPrintObject;
            var strFileExt:String = "png"
            var variables:URLVariables = new URLVariables(); 
            variables.mimeType = "application/octet-stream";
            variables.fileExt = strFileExt;
            baPanel.position = 0;
            var strPanel:String = getBytes(baPanel);
//          var strPanel:String = baPanel.readMultiByte(baPanel.bytesAvailable,"latin1");
            variables.fileContents = escape(strPanel);
            trace('strPanel.length=' + strPanel.length + ' baPanel.length=' + baPanel.length);
            variables.disposition = "Attachment";
            variables.fileName = strFileName;
            var u:URLRequest = new URLRequest( RootDomain + "SendBinaryFile2.aspx");
            u.data = variables; 
            u.method = "POST"; 
            navigateToURL(u,"_blank"); 
    }
    catch (err:Error)
    {
        Alert.show("This Panel cannot be copied to the clipboard. \nSorry for the inconvenience \nError: " + err.errorID,"E-mail not premitted",Alert.OK)
    }

(I left the clipboard stuff commented out in case someone knows how to do that. It is my understanding that you cannot send binary data to the clipboard from Flash, but it works in AIR.)

Since I could not find an AS3 method to convert a binary ByteArray to a string I wrote my own called getBytes. If you know of a method in AS3, please let me know.

    private function getBytes(baArray:ByteArray):String
{
    var strOut:String = "";
    baArray.position = 0;
    var intBASize:int = baArray.bytesAvailable;
    for (var i:int = 0;i < intBASize;i++)
    {
        strOut += String.fromCharCode(baArray.readByte()); 
    }
    return strOut;
}

On the ASPX side I have a file called SendBinaryFile2.aspx that looks like this;

<%@ Page Language="C#" validateRequest="false"%>
<script Runat="Server">

void Page_Load(Object sender, EventArgs e)
{
    string fileExt = Request.Form["fileExt"];
    string mimeType = Request.Form["mimeType"];
    string disposition = Request.Form["disposition"];
    string fileName = Request.Form["fileName"];
    byte [] fileContents = Encoding.ASCII.GetBytes(HttpUtility.UrlDecode(Request.Form["fileContents"]));

    Response.Buffer = true;
    Response.Clear();
    Response.AddHeader("Content-Length", fileContents.Length.ToString());
    Response.ContentType = mimeType;
    Response.AddHeader("Content-Disposition", disposition + "; filename=" + fileName + "." + fileExt);
    Response.BinaryWrite(fileContents);
    Response.Flush();
    Response.Close();
    Response.End();
}
</script>

The results is a file that looks a whole lot like a .PNG file, but is corrupt when it is opened. I have visually compared the file sent via email, and the one sent via this program using VIM, and they look similar, have roughly the same number of characters, begin/end with similar characters.

Help on any of the items defined above is greatly appreciated.

Paul Stearns
  • 856
  • 9
  • 30
  • You can try to convert in base64 string. See more [here](http://stackoverflow.com/questions/6596341/actionscript-image-to-base64-string-possible): – Rodolpho Silva Mar 30 '16 at 18:08
  • I hope my answer helps but why send to browser just to save a file? I mean you could directly save a file in AS3 using `FileReference` class. – VC.One Mar 31 '16 at 00:14
  • VC.One I gave you credit on your answer, but I actually used the FileReference. I never used this before, but it seems like exactly what I needed. If anyone needs I could actually make it work the other way and provide my results. – Paul Stearns Mar 31 '16 at 22:42
  • Glad it's sorted. Yes just saving `baPanel` (after PNG encode) using fileReference gives you the image on disk. Less hassle?. PS: use @ symbol to give user notifications otherwise I would have missed your comment. Thanks – VC.One Mar 31 '16 at 23:20

2 Answers2

2

Try this for your getBytes function...

private function getBytes (baArray:ByteArray) : String
{
    var strOut:String = ""; var strRead:String = "";
    baArray.position = 0;
    var intBASize:uint = baArray.length;

    for (var i:int = 0; i < intBASize; i++)
    {
        strRead = baArray.readUnsignedByte().toString(16); 

        if(strRead.length < 2) { strRead = "0" + strRead; } //# do padding
        strOut += strRead ;     
    }

    return strOut.toUpperCase();
}

This should give you padded bytes. Consider x0FF3 becomes just xFF3 without the padding, later the other side could be assuming the bytes are really xFF30 leading to corrupt images.

VC.One
  • 14,790
  • 4
  • 25
  • 57
  • VC.One This will return a string that contains the hex values of the string, as opposed to the actual binary string. I assume that I would remove the "escape" from the line "variables.fileContents = escape(strPanel);". What do I use on the C# side to convert a string of hex characters to the actual binary data? – Paul Stearns Mar 31 '16 at 22:17
  • Do you want the format as "zeros & ones" instead of hex? Let me know cos the padding code is different for that format. If you keep it as hex, then base64 encode that before copying to clipboard the browser can then decode the base64 to a displayable image. – VC.One Mar 31 '16 at 22:28
1

I'd suggest you use Base64 encoding to transport your binary data. You already must have needed to use it for encoding your email attachment, anyways.

Actionscript: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/utils/Base64Encoder.html

c#:

byte[] textAsBytes = System.Convert.FromBase64String(encodedText);

Also, if your SWF is running as standalone AIR (You wrote "Flex program"...), you can directly save files anywhere and give the user a "Save as..." prompt to do so.

Source to save from AIR:

var bmpd:BitmapData = new BitmapData(myWidth, myHeight, true, 0);
bmpd.draw(mySource);
var imgByteArray:ByteArray = new PNGEncoder().encode(bmpd);
var fl:File = File.desktopDirectory.resolvePath("myImage.png");
var fs:FileStream = new FileStream();
fs.open(fl, FileMode.WRITE);
fs.writeBytes(imgByteArray);
fs.close();
geesys
  • 11
  • 3