How do I Pass an Image from Flash to ASP.NET? - asp.net

Quick version:
How do I get an image that was generated on the users browser back to the server?
The current plan is this:
The Flash developer will convert the bitmap to JPEG
He will then POST the JPEG to a page on the site.
I'm thinking I can create a WebService which will use a StreamReader to read the post and save it as a file.
Would that work? Any existing code/samples for doing this?
I suppose we should be able to look at code for doing any file upload to ASP.NET.

In this example, I've created a Flash file with a button on the stage. When you click that button, the Flash sends the image of the button to an ASPX file which saves it out as a JPEG. As you'll see this is done by drawing the DisplayObject into a BitmapData object and as such, you can easily replace the reference to the button with anything that inherits from DisplayObject (including a movie clip that contains the canvas for a paint application etc).
I’ll walk you through the Flash element first and then the .NET backend.
Flash
To send a generated image like this from Flash to ASP.NET (or any other backend) you’re going to need a couple of 3rd party libraries. We’ll need a JPEG Encoder (which Flash doesn’t have, but recent versions of Flex do) which we can get from the AS3 Core Lib http://code.google.com/p/as3corelib/. We’ll also need a base64 encoder for sending the data over the wire. I’ll use the one from Dynamic Flash, available at http://dynamicflash.com/goodies/base64/.
Download these and extract them somewhere sensible on your hard disk (like a C:\lib folder).
I created a new AS3 Flash file and saved it as uploader.fla. I added a button component to the stage and named it btnUpload. Next I edited the ActionScript settings and added my c:\lib folder to the classpath. Then I gave the document a class name of Uploader and saved the file.
Next, I created an ActionScript file and added the following code to it:
package
{
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import flash.utils.ByteArray;
import fl.controls.Button;
import com.adobe.images.JPGEncoder;
import com.dynamicflash.util.Base64;
public class Uploader extends MovieClip
{
// Reference to the button on the stage
public var btnUpload:Button;
// Encoder quality
private var _jpegQuality:int = 100;
// Path to the upload script
private var _uploadPath:String = "/upload.aspx";
public function Uploader()
{
btnUpload.addEventListener(MouseEvent.CLICK, buttonClick);
}
private function buttonClick(e:MouseEvent):void
{
// Create a new BitmapData object the size of the upload button.
// We're going to send the image of the button to the server.
var image:BitmapData = new BitmapData(btnUpload.width, btnUpload.height);
// Draw the button into the BitmapData
image.draw(btnUpload);
// Encode the BitmapData into a ByteArray
var enc:JPGEncoder = new JPGEncoder(_jpegQuality);
var bytes:ByteArray = enc.encode(image);
// and convert the ByteArray to a Base64 encoded string
var base64Bytes:String = Base64.encodeByteArray(bytes);
// Add the string to a URLVariables object
var vars:URLVariables = new URLVariables();
vars.imageData = base64Bytes;
// and send it over the wire via HTTP POST
var url:URLRequest = new URLRequest(_uploadPath);
url.data = vars;
url.method = URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
loader.load(url);
}
}
}
I saved this file next to the FLA with the name Uploader.as.
I published the SWF into the root of my Asp.NET website.
This code assumes you want to upload the jpeg with a quality of 100% and that the script which will receive the data is called upload.aspx and is located in the root of the site.
ASP.NET
In the root of my website I created a WebForm named upload.aspx. In the .aspx file, i removed all the content apart from the page directive. It’s content look like this:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="upload.aspx.cs" Inherits="upload" %>
Then in the CodeBehind, I added the following:
using System;
using System.IO;
public partial class upload : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Get the data from the POST array
string data = Request.Form["imageData"];
// Decode the bytes from the Base64 string
byte[] bytes = Convert.FromBase64String(data);
// Write the jpeg to disk
string path = Server.MapPath("~/save.jpg");
File.WriteAllBytes(path, bytes);
// Clear the response and send a Flash variable back to the URL Loader
Response.Clear();
Response.ContentType = "text/plain";
Response.Write("ok=ok");
}
}
There are obviously hard-coded values such as the save path but from this you should be able to create whatever system you require.

If you need to manipulate the image, as long as you can get a byte[] or a Stream of the POSTed file, you can create an image of it, e.g.
MemoryStream mstr = new MemoryStream(myByteArray);
Image myImage = Image.FromStream(mstr);

Have him post the files like a standard HTML form. You can access those files in the Page_Load event of the page he is posting to by using the following collection
Request.Files
This will return a collection of HttpPostedFiles just like what a FileUpload control does.

Related

child of child movie clip are null in imported object from flex to flash right after being created

I have an Movie Clip in Flash that have subobject of button type which has subobject of input text and movie clips. Right after creation core Moveclip all subobject are set to null, when I expect them to be valid objects.
// hierarchy:
// core:MC_Core_design
// button_1:B_Mybutton
// text_name // dynamic text with instance name
// mc_icon // movie clip with instance name
var core:MC_Core_design = new MC_Core_design();
addChild(core);
core.button_1.text_name.text = "hello world"; // error: text_name is null
core.button_1.mc_icon.visible = false; // error: mc_icon is null
MC_Core_design was created in Flash and exported to Actionscript. I've done this for button_1 class aswell. The code was written using Flex.
When I comment out both lines that result in error I get correct view of the core Movie clip with all subobject.
How can I set subobject properties right after object creation?
You need to listen for the Event.INIT from the class when it is created. (If you are not embedding a symbol using the Embed metatag then Flash takes a few milliseconds to initialize the loaded movieclip). This does not seem to be a problem if the Flash IDE swf/swc does not contain any actionscript)
The issue is sometimes it can be really quick, so it fires the INIT event before you get a chance to attach the event listener to the object. so you can't just attach it after you instantiate the object.
A work around is to embed the swf as a byte array, then use the loader class to load the embedded bytes (This lets you set the event listener before calling load).
e.g.
[Embed(source="assets.swf", mimeType="application/octet-stream")]
private var assetBytes:Class;
private var clip:MovieClip;
private var loader:Loader;
public function LoadBytesExample()
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, onAssetLoaded);
loader.loadBytes(new assetBytes());
}
private function onAssetLoaded(e:Event):void
{
var loader:Loader = (e.currentTarget as LoaderInfo).loader;
(e.currentTarget as LoaderInfo).removeEventListener(Event.INIT, onAssetLoaded);
clip = loader.content as MovieClip;
this.addChild(clip);
clip.someTextField.text = "HELLO WORLD";
}
Sorry for the formatting, just wrote that off the top of my head
And the syntax for embedding the symbol (You won't need to load this via a loader as the actionscript in the external swf/swc is stripped).
[Embed(source="assets.swf", symbol="somesymbol")]
private var assetSymbol:Class;
private var clip:MovieClip;
public function LoadSymbolExample()
{
clip = new assetSymbol();
clip.sometext.text = "Hello World";
}
If I see it right, button_1:B_Mybutton is not yet initialized.
I mean something like : button_1:B_Mybutton = new B_Mybutton();
About the other two variables text_name & mc_icon as you describe if they have been initialized already (as you term them as instance names), Iguess they should not give you any problem.
Also I asssume that you are setting access modifiers to all as public.
If you still have problem... pls share how all the required variables are defined. Just the relevant part would be enough.

How to upload files in flex using PyAMF or PhpAMF? client side, and very little server side help needed

Hy!
I need to upload a group of images using flex with robotlegs.
I need a progress bar to work when image is uploading.
It might upload 1 image or more at the time.
I want to know if uploading byteArray to server and then save the image is too heavy for the server.
In the server side I have a method that is made by pyamf, and looks like this:
.
def upload_image(input):
# here does stuff. I need to be able to get parametters like this
input.list_key
# and here I need some help on how to save the file
Thanks ;)
I had to tackle a similar problem (uploading single photo from Flex to Django) while working on captionmash.com, maybe it can help you. I was using PyAMF for normal messaging but FileReference class had a built in upload method, so I chose the easy way.
Basically system allows you to upload a single file from Flex to Google App Engine, then it uses App Engine's Image API to create thumbnail and also convert image to JPEG, then upload it to S3 bucket. boto library is used for Amazon S3 connection, you can view the whole code of the project here on github.
This code is for single file upload only, but you should be able to do multi-file uploads by creating an array of FileReference objects and calling upload method on all of them.
The code I'm posting here is a bit cleaned up, if you still have problems you should check the repo out.
Client Side (Flex):
private function upload(fileReference:FileReference,
album_id:int,
user_id:int):void{
try {
//500 kb image size
if(fileReference.size > ApplicationConstants.IMAGE_SIZE_LIMIT){
trace("File too big"+fileReference.size);
return;
}
fileReference.addEventListener(Event.COMPLETE,onComplete);
var data:URLVariables = new URLVariables();
var request:URLRequest = new URLRequest(ApplicationConstants.DJANGO_UPLOAD_URL);
request.method = URLRequestMethod.POST;
request.data = data;
fileReference.upload(request,"file");
//Popup indefinite progress bar
} catch (err:Error) {
trace("ERROR: zero-byte file");
}
}
//When upload complete
private function onComplete(evt:Event):void{
fileReference.removeEventListener(Event.COMPLETE,onComplete);
//Do other stuff (remove progress bar etc)
}
Server side (Django on App Engine):
Urls:
urlpatterns = patterns('',
...
(r'^upload/$', receive_file),
...
Views:
def receive_file(request):
uploadService = UploadService()
file = request.FILES['file']
uploadService.receive_single_file(file)
return HttpResponse()
UploadService class
import uuid
from google.appengine.api import images
from boto.s3.connection import S3Connection
from boto.s3.key import Key
import mimetypes
import settings
def receive_single_file(self,file):
uuid_name = str(uuid.uuid4())
content = file.read()
image_jpeg = self.create_jpeg(content)
self.store_in_s3(uuid_name, image_jpeg)
thumbnail = self.create_thumbnail(content)
self.store_in_s3('tn_'+uuid_name, thumbnail)
#Convert image to JPEG (also reduce size)
def create_jpeg(self,content):
img = images.Image(content)
img_jpeg = images.resize(content,img.width,img.height,images.JPEG)
return img_jpeg
#Create thumbnail image using file
def create_thumbnail(self,content):
image = images.resize(content,THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT,images.JPEG)
return image
def store_in_s3(self,filename,content):
conn = S3Connection(settings.ACCESS_KEY, settings.PASS_KEY)
b = conn.get_bucket(BUCKET_NAME)
mime = mimetypes.guess_type(filename)[0]
k = Key(b)
k.key = filename
k.set_metadata("Content-Type", mime)
k.set_contents_from_string(content)
k.set_acl("public-read")

An image from byte to optimized web page presentation

I get the data of the stored image on database as byte[] array;
then I convert it to System.Drawing.Image like the code shown below;
public System.Drawing.Image CreateImage(byte[] bytes)
{
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(bytes);
System.Drawing.Image image = System.Drawing.Image.FromStream(memoryStream);
return image;
}
(*) On the other hand I am planning to show a list of images on asp.net pages as the client scrolls downs the page. The more user gets down and down on the page he/she does see the more photos. So it means fast page loads and rich user experience. (you may see what I mean on www.mashable.com, just take care the new loads of the photos as you scroll down.)
Moreover, the returned imgae object from the method above, how can i show it in a loop dynamically using the (*) conditions above.
Regards
bk
Well, I think the main bottleneck is actually hitting the database each time you need an image. (Especially considering many users accessing the site.)
I would go with the following solution:
Database will store images with the original quality;
.ashx handler will cache images on the file system in various needed resolutions (like 32x32 pixels for icons, 48x48 for thumbnails, etc.) returning them on request and accessing database only once; (in this example is shown how to return an image via ashx handler)
The actual pages will point to .ashx page to get an image. (like <img scr="GetImage.ashx?ID=324453&Size=48" />)
UPDATE:
So the actual workflow in the handler will be like:
public void ProcessRequest (HttpContext context)
{
// Create path of cached file based on the context passed
int size = Int32.Parse(context.Request["Size"]);
// For ID Guids are possibly better
// but it can be anything, even parameter you need to pass
// to the web service in order to get those bytes
int id = Int32.Parse(context.Request["Id"]);
string imagePath = String.Format(#"images/cache/{0}/{1}.png", size, id);
// Check whether cache image exists and created less than an hour ago
// (create it if necessary)
if (!File.Exists(imagePath)
|| File.GetLastWriteTime(imagePath) < DateTime.Now.AddHours(-1))
{
// Get the file from the web service here
byte[] imageBytes = ...
// Save as a file
using (var memoryStream = new MemoryStream(imageBytes))
using (var outputStream = File.OpenWrite(imagePath))
Image.FromStream(memoryStream).Save(outputStream);
}
context.Response.ContentType = "image/png";
context.Response.WriteFile(imagePath);
}

Embedding jQuery into your ASP.Net Server Custom Control

I am undergraduate student. I had some queries related to embedding jQuery inside your ASP.NET Server side Custom Control.
private string GetEmbeddedTextFile(string sTextFile)
{
// generic function for retrieving the contents
// of an embedded text file resource as a string
// we'll get the executing assembly, and derive
// the namespace using the first type in the assembly
Assembly a = Assembly.GetExecutingAssembly();
String sNamespace = a.GetTypes()[0].Namespace;
// with the assembly and namespace, we'll get the
// embedded resource as a stream
Stream s = a.GetManifestResourceStream(
string.Format("{0}.{1}",a.GetName().Name, sTextFile)
);
// read the contents of the stream into a string
StreamReader sr = new StreamReader(s);
String sContents = sr.ReadToEnd();
sr.Close();
s.Close();
return sContents;
}
private void RegisterJavascriptFromResource()
{
// load the embedded text file "javascript.txt"
// and register its contents as client-side script
string sScript = GetEmbeddedTextFile("JScript.txt");
this.Page.RegisterClientScriptBlock("PleaseWaitButtonScript", sScript);
}
private void RegisterJQueryFromResource()
{
// load the embedded text file "javascript.txt"
// and register its contents as client-side script
string sScript = GetEmbeddedTextFile("jquery-1.4.1.min.txt");
this.Page.ClientScript.RegisterClientScriptBlock(typeof(string), "jQuery", sScript);
// this.Page.RegisterClientScriptBlock("JQueryResourceFile", sScript);
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
// the client-side javascript code is kept
// in an embedded resource; load the script
// and register it with the page.
RegisterJQueryFromResource();
RegisterJavascriptFromResource();
}
but the problem I am facing is that all my JQuery code which I have written in separate .JS file and have tried to embed in my Custom control , is streamed as output on the screen . Also , my Control is not behaving correctly as it should have to , jQuery functionality is not working behind due to this reason of not getting embedded properly :-(
Please help me out!
Thank you!
It sounds like you are missing the <script> tags surrounding the javascript. Try this overload of RegisterClientScriptBlock that takes a fourth boolean parameter that will add the script tags if it is true.
Page.ClientScript.RegisterClientScriptBlock(typeof(string), "jQuery", sScript, true);
"all my JQuery code which I have written in separate .JS file and have tried to embed in my >Custom control , is streamed as output on the screen" .
Sounds like you need to add a line that tells the code how to download the embedded javascript. Do it with an Assembly annotation above the start of a class in your custom control project. This is the format:
<Assembly: System.Web.UI.WebResource("Namespace.ScriptName.js", "application/x-javascript")>

How to pass content of image file from fileupload control to web method via javascript?

I have a problem with using binary content of file. I want to pass web method content of file. I retriev it from fileupload control on my page via javascript function getAsBinary(). But error appears in web method, when I try to create example of class Image.
So, I have the page (.aspx) with fileupload control and scriptmanager. There are three javascript function:
// Get image from fileupload control and pass it in webmethod
function Get_image() {
var file_uploader = document.getElementById(file_uploader_name);
var file_content = file_uploader.files[0].getAsBinary();
imupcon.Get_image(file_content, OnRequestComplete, OnError);
}
// Successful execution
function OnRequestComplete(result) {alert(result);}
//Error execution
function OnError() { alert("Error!");}
And I have web-service with web-method:
[WebMethod]
public string Get_image(string file_content, string file_name)
{
byte[] data = Encoding.Unicode.GetBytes(file_content);
MemoryStream memStream = new MemoryStream();
memStream.Write(data, 0, data.Length);
//Error appears here
System.Drawing.Image image = System.Drawing.Image.FromStream(memStream);
memStream.Close();
return "Hurray!";
}
Does any have idea, what is reason? How I can pass content of file to web method? Thanks.
You don't need Encoding.Unicode.GetBytes if it's as it's already in binary. The data would be in unicode if you called files[0].getAsText("utf-8"). Please note that all of these methods are now obsolete and you should use feature detection and use the standard FileReader API if it is available.

Resources