I am trying to transfer a movie-clip staged in a swf(on local machine) to a remote server. Below is a part of the action-script code concerned with it;
function createJPG(mc:MovieClip, n:Number, fileName:String) {
trace("sdf:");
var jpgSource:BitmapData = new BitmapData(mc.width,mc.height);
jpgSource.draw(mc);
var jpgEncoder:JPGEncoder = new JPGEncoder(n);
var jpgStream:ByteArray = jpgEncoder.encode(jpgSource);
trace("jpegStream::"+jpgStream);
var header:URLRequestHeader = new URLRequestHeader("Content-type","application/octet-stream");
var jpgURLRequest:URLRequest = new URLRequest("http://example.com/arts/savefile.php?name=" + fileName + ".jpg");
jpgURLRequest.requestHeaders.push(header);
jpgURLRequest.method = URLRequestMethod.POST;
jpgURLRequest.data = jpgStream;
var loader:URLLoader = new URLLoader();
trace("navigatetoURL:");
sendToURL(jpgURLRequest); }
The php script in the remote server to save the file is;
<?php
set_time_limit(0);
if( isset($GLOBALS['HTTP_RAW_POST_DATA']) ) {
$imageFile='images/'.$_GET['name'];
$fp = fopen($imageFile, 'w+');
// get bytearray
fwrite($fp, $GLOBALS['HTTP_RAW_POST_DATA']);
fclose($fp);
if( file_exists($imageFile) ) {
echo 'File saved.';
}
else {
echo 'Error: Problem writing the file.';
}
}
else {
echo 'Error: Not data available to write the file.';
}
?>
I want to close the swf when the upload is complete., I would like to know how to return a value(may be a number which I intend to use to indicate completion of file transfer) from the php script to the swf and how to receive that value in the swf?
Would really appreciate any help.
Thanks!.
The URLLoader supports an Event.COMPLETE event, which is fired when your remote operation returns data and that data has been stored in URLRequest.data.
From PHP, the data that you echo is what Flash will receive, so you might want to consider a more complex data type than a single string, maybe use json and pass an object that looks like:
{result:1,message:"some message"};
This gives you a simple 1/0 result value for easy checking and a string message for output to the user. You would do that in PHP by creating an associative array and encoding it with JSON.encode().
Then on the Flash side you will add an event listener to your URLLoader to detect the COMPLETE event, and use the JSON class from the Adobe core library to decode your PHP output to a useable object.
I always use AMFPHP nowadays http://sourceforge.net/projects/amfphp/ . Gotoandlearn has a nice free tutorial on it http://www.gotoandlearn.com/ .
Related
I have a video player built in AS3. I take a snapshot of the video player using this code:
var uploadUrl = 'http://localhost:8000/assets/uploadframegrab';
var bitmap = new Bitmap();
var graphicsData : Vector.<IGraphicsData>;
graphicsData = container.graphics.readGraphicsData();
bitmap.bitmapData = GraphicsBitmapFill(graphicsData[0]).bitmapData;
var jpgEncoder:JPGEncoder = new JPGEncoder(85);
var jpgStream:ByteArray = jpgEncoder.encode(bitmap.bitmapData);
var loader:URLLoader = new URLLoader();
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
var csrf:URLRequestHeader = new URLRequestHeader("X-CSRF-Token", csrfToken);
var request:URLRequest = new URLRequest(uploadUrl);
request.requestHeaders.push(header);
request.requestHeaders.push(csrf);
request.method = URLRequestMethod.POST;
request.data = jpgStream;
loader.load(request);
I need to upload the encoded to JPG using one of my Laravel routes. My route looks like:
Route::post('assets/uploadframegrab', 'AssetController#uploadFramegrab');
When I run the AS3 code, it calls the laravel route, but my $request variable appears to be empty. The Request Payload property on the network info tab that shows all my headers and stuff contains what looks like the source of the image file.
If I do a return Response::json(['filedata' => $request]); all I get is this:
filedata: {
attributes: {},
request: {},
query: {},
server: {},
files: {},
cookies: {},
headers: {}
}
My uploadFramegrab function is simply this for now:
public function uploadFramegrab(Request $request)
{
if ($request)
{
return Response::json(['filedata' => $request]);
}
else
{
return Response::json(['error' => 'no file uploaded']);
}
}
I've searched online but I cannot find anything specifically for uploading from flash to laravel. I've done it javascript to laravel no problem. Anyone know what this could be? If you'd like more information please ask.
To do that, you can use the Multipart.as ( AS3 multipart form data request generator ) from Jonas Monnier. It's really very easy to use it, take a look on this example ( using the basic example from the github project's page ) :
var upload_url:String = 'http://www.example.com/upload';
// create an orange square
var bmp_data:BitmapData = new BitmapData(400, 400, false, 0xff9900);
// compress our BitmapData as a jpg image
var image:ByteArray = new JPGEncoder(75).encode(bmp_data);
// create our Multipart form
var form:Multipart = new Multipart(upload_url);
// add some fields if you need to send some informations
form.addField('name', 'bmp.jpg');
form.addField('size', image.length.toString());
// add our image
form.addFile('image', image, 'image/jpeg', 'bmp.jpg');
var loader:URLLoader = new URLLoader();
loader.load(form.request);
Then, in the PHP side, you do as you have usually did :
public function upload(\Illuminate\Http\Request $request)
{
if($request->hasFile('image'))
{
$file = $request->file('image');
$upload_success = $file->move($your_upload_dir, $file->getClientOriginalName());
if($upload_success)
{
return('The file "'.$request->get('name').'" was successfully uploaded');
}
else
{
return('An error has occurred !');
}
}
return('There is no "image" file !');
}
Hope that can help.
Based on the doc for AS3 (emphasis mine):
The way in which the data is used depends on the type of object used:
If the object is a ByteArray object, the binary data of the ByteArray object is used as POST data. For GET, data of ByteArray type is not supported. Also, data of ByteArray type is not supported for FileReference.upload() and FileReference.download().
If the object is a URLVariables object and the method is POST, the variables are encoded using x-www-form-urlencoded format and the resulting string is used as POST data. An exception is a call to FileReference.upload(), in which the variables are sent as separate fields in a multipart/form-data post.
You're clearly in the first case here.
From the Laravel Requests doc:
To obtain an instance of the current HTTP request via dependency injection, you should type-hint the Illuminate\Http\Request class on your controller constructor or method. The current request instance will automatically be injected by the service container.
The Request class API:
string|resource getContent(bool $asResource = false)
Returns the request body content.
Putting it together:
public function uploadFramegrab(Request $request) {
$content = $request->getContent();
$fileSize = strlen($content);
}
In Laravel 4:
$csrf = Request::header('X-CSRF-Token');
// Add a header like this if you want to control filename from AS3
$fileName = Request::header('X-File-Name');
$content = Request::getContent(); // This the raw JPG byte array
$fileSize = strlen($content);
Last time I checked Laravel uses php://input to read the request body. See this answer for more info.
I have been searching for a good method, and banging my head against the wall.
In a file sharing service project, I have been assigned to determine the best method available for upload large files.
After searching a lot of questions here on stackoverflow and other forums, here's what I got :
Increase the script maximum execution time, along with maximum file size allowed
This case really doesn't fit good. It will almost timeout everytime when the file is being uploaded through a normal broadband connection (1mbps-2mbps). Even if PHP scripts are executed after the upload has been done, there is still no guarantee that the upload will not timeout.
Chunked upload.
Although I kind of understand what I'm supposed to do here, but what I'm confused about is that, say a 1GB file is being uploaded, and I'm reading it in chunks of 2MB, still if the upload is slow, the php script execution will timeout and give error.
Use other languages like Java and Perl?
Is it really efficient to use java or perl for handling file uploads?
Method used by the client is not the problem here, as we'll be issuing a client SDK, and can implement the method of our choice in it. Both the client and server end implementations will be decided by us.
What method, according to you, should be the best one, considering that the memory usage should be efficient, and there may be many concurrent uploads going on?
How do Dropbox, and similar cloud storage services handle big file uploads, and still stay fast at it?
I suggest you use PHP I/O streams with AJAX. This will keep the memory footprint low on the server and you can easily build an async file upload. Note that this uses the HTML5 API which is available only in modern browsers.
Check out this post: https://web.archive.org/web/20170803172549/http://www.webiny.com/blog/2012/05/07/webiny-file-upload-with-html5-and-ajax-using-php-streams/
Pasting the code from the article here:
HTML
<input type="file" name="upload_files" id="upload_files" multiple="multiple">
JS
function upload(fileInputId, fileIndex)
{
// take the file from the input
var file = document.getElementById(fileInputId).files[fileIndex];
var reader = new FileReader();
reader.readAsBinaryString(file); // alternatively you can use readAsDataURL
reader.onloadend = function(evt)
{
// create XHR instance
xhr = new XMLHttpRequest();
// send the file through POST
xhr.open("POST", 'upload.php', true);
// make sure we have the sendAsBinary method on all browsers
XMLHttpRequest.prototype.mySendAsBinary = function(text){
var data = new ArrayBuffer(text.length);
var ui8a = new Uint8Array(data, 0);
for (var i = 0; i < text.length; i++) ui8a[i] = (text.charCodeAt(i) & 0xff);
if(typeof window.Blob == "function")
{
var blob = new Blob([data]);
}else{
var bb = new (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)();
bb.append(data);
var blob = bb.getBlob();
}
this.send(blob);
}
// let's track upload progress
var eventSource = xhr.upload || xhr;
eventSource.addEventListener("progress", function(e) {
// get percentage of how much of the current file has been sent
var position = e.position || e.loaded;
var total = e.totalSize || e.total;
var percentage = Math.round((position/total)*100);
// here you should write your own code how you wish to proces this
});
// state change observer - we need to know when and if the file was successfully uploaded
xhr.onreadystatechange = function()
{
if(xhr.readyState == 4)
{
if(xhr.status == 200)
{
// process success
}else{
// process error
}
}
};
// start sending
xhr.mySendAsBinary(evt.target.result);
};
}
PHP
// read contents from the input stream
$inputHandler = fopen('php://input', "r");
// create a temp file where to save data from the input stream
$fileHandler = fopen('/tmp/myfile.tmp', "w+");
// save data from the input stream
while(true) {
$buffer = fgets($inputHandler, 4096);
if (strlen($buffer) == 0) {
fclose($inputHandler);
fclose($fileHandler);
return true;
}
fwrite($fileHandler, $buffer);
}
May be the tus HTTP-based resumable file upload protocol and its implementations?
https://tus.io/
https://github.com/tus
https://github.com/ankitpokhrel/tus-php
I know there is a lot of questions regarding this but currently I am trying to save user created HTML5 canvas data to a specific folder on my web server.
I am already able to save an image to server using the following:
function sendData(postData){
var ajax = new XMLHttpRequest();
ajax.open("POST",'saveFrame.php',true);
ajax.setRequestHeader('Content-Type', 'canvas/upload');
var comicID = document.getElementById('comicID').value;
ajax.onreadystatechange=function()
{
if (ajax.readyState == 4)
{
alert("Frame saved");
}
}
ajax.send(postData);
}
saveFrame.PHP File
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
// Get the data like you would with traditional post
$rawImage=$GLOBALS['HTTP_RAW_POST_DATA'];
// Remove the headers
$removeHeaders=substr($rawImage, strpos($rawImage, ",")+1);
// decode it from base 64 and into image data only
$decode=base64_decode($removeHeaders);
// save to your server
$saveName = "test.jpeg";
$fopen = fopen($saveName, 'wb' );
fwrite( $fopen, $decode);
fclose( $fopen );
}
?>
What I want to be able to do is pass some more variables along side the image so that I can dynamically look up my database using PHP within the saveFrame.php file to determine what filename it should be saved as. I'm unsure how to accomplish this as I'm not accustomed to using AJAX.
Any advice is appreciated,
Alex
You can use the html5 canvaspixelarray property to obtain the canvas data.
First off, I am very bad at flash/actionscript, it is not my main programming language.
I have created my own file upload flash app that has been working great for me up until this point. It uses PHP to upload the files and sends back a status message which gets displayed in a status box to the user.
Now I have run into a situation where I need the HTML to pass a parameter to the Actionscript, and then to the PHP file using POST. I have tried to set this up just like adobe has it on http://livedocs.adobe.com/flex/3/html/help.html?content=17_Networking_and_communications_7.html without success.
Here is my Actionscript code
import fl.controls.TextArea;
//Set filters
var imageTypes:FileFilter = new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg; *.jpeg; *.gif; *.png");
var textTypes:FileFilter = new FileFilter("Documents (*.txt, *.rtf, *.pdf, *.doc)", "*.txt; *.rtf; *.pdf; *.doc");
var allTypes:Array = new Array(textTypes, imageTypes);
var fileRefList:FileReferenceList = new FileReferenceList();
//Add event listeners for its various fileRefList functions below
upload_buttn.addEventListener(MouseEvent.CLICK, browseBox);
fileRefList.addEventListener(Event.SELECT, selectHandler);
function browseBox(event:MouseEvent):void {
fileRefList.browse(allTypes);
}
function selectHandler(event:Event):void {
var phpRequest:URLRequest = new URLRequest("ajax/upload.ajax.php");
var flashVars:URLVariables = objectToURLVariables(this.root.loaderInfo);
phpRequest.method = URLRequestMethod.POST;
phpRequest.data = flashVars;
var file:FileReference;
var files:FileReferenceList = FileReferenceList(event.target);
var selectedFileArray:Array = files.fileList;
var listener:Object = new Object();
for (var i:uint = 0; i < selectedFileArray.length; i++) {
file = FileReference(selectedFileArray[i]);
try {
file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, phpResponse);
file.upload(phpRequest);
}
catch (error:Error) {
status_txt.text = file.name + " Was not uploaded correctly (" + error.message + ")";
}
}
}
function phpResponse(event:DataEvent):void {
var file:FileReference = FileReference(event.target);
status_txt.htmlText += event.data;
}
function objectToURLVariables(parameters:Object):URLVariables {
var paramsToSend:URLVariables = new URLVariables();
for(var i:String in parameters) {
if(i!=null) {
if(parameters[i] is Array) paramsToSend[i] = parameters[i];
else paramsToSend[i] = parameters[i].toString();
}
}
return paramsToSend;
}
The flashVars variable is the one that should contain the values from the HTML file. But whenever I run the program and output the variables in the PHP file I receive the following.
//Using this command on the PHP page
print_r($_POST);
//I get this for output
Array
(
[Filename] => testfile.txt
[Upload] => Submit Query
)
Its almost like the parameters are getting over written or are just not working at all.
Thanks for any help,
Metropolis
Try...
print_r($_FILES);
Like I said in my comment: Do you successfully receive the variable in Flash from the flashvars?
I haven't done Flash in a while but maybe, instead of your objectToURLVariables function, just referencing each variable directly is a better way. At least to figure out if you have those variables from your HTML page. So maybe do something like this:
var myVar:String = LoaderInfo(this.root.loaderInfo).parameters.myVar;
var flashVars:URLVariables = objectToURLVariables(myVar);
Ok, I have fixed the issue somehow.....I kept changing things back and forth and realized that the cache had not been cleared in awhile. I cleared the cache and it started working for some reason.
I did change one line back to the way I had it before.
I changed
var flashVars:URLVariables = objectToURLVariables(this.root.loaderInfo);
To
var flashVars:URLVariables = objectToURLVariables(root.loaderInfo.parameters);
Im not positive that this was causing the problem. It may have been that I just needed to clear the cache the whole time. Anyway, thanks for your help guys.
is it possible to call a PHP function from flash and have it execute right away?
If so how could I go about doing that, because I am trying to call a PHP function that will update a users facebook status, but thus far I have been unsuccessful, so I am kind of at the end f my rope.
Any help would be appreciated, thanx!
My idea would be something similar to the following:
function updateFBStatus(newStatus)
{
// create two new instances of LoadVars, one to send and one to receive data
var dataOut:LoadVars = new LoadVars();
var dataIn:LoadVars = new LoadVars();
// define what should happen when the response is received,
// using 'this' to refer to dataIn and get data from it
dataIn.onLoad = onReturn;
dataOut["newStatus"] = newStatus;
dataOut.sendAndLoad(serverURL+"setFBStatus.php", dataIn, "POST");
}
You then define the setFBStatus.php file on your server to read $_POST['newStatus'] and do whatever you would normally do in php to set the facebook status. That php file can optionally echo some return values in url request format (i.e, paramName1=param1¶mName2=param2&) for your onReturn function to read, if you need to.
Have a look at AMF PHP!
Save the PHP function in facebookFunction.php and call it using a URLLoader.
var urlLoader:URLLoader = new URLLoader();
var data:URLVariables = new URLVariables();
//you can use dot syntax and/or [] syntax to add data.
data.user = "kiele";
data["someThingElse"] = "something else";
var req:URLRequest = new URLRequest("facebookFunction.php");
req.data = data;
urlLoader.load(req);
At the php side, you can read the values from the global get variable.
$user = $_GET["user"]
The way I would do it is in the flash actionscript is call a javascript function using getURL("javascript:someFunction(var-1, var-2, var-n)") http://www.adobe.com/livedocs/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001180.html
That javascript function can then do an ajax request to a php script.
EDIT:
you could just post data directly without using AJAX:
var firstName:String = "Gus";
var lastName:String = "Richardson";
var age:Number = 92;
getURL("http://www.adobe.com", "_blank", "POST");
Why you are not using a Flash API for Facebook: http://code.google.com/p/facebook-actionscript-api/ ?