as3 / php mp3 байтовый массив транспорта и записи - PullRequest
1 голос
/ 03 февраля 2012

Я уже некоторое время бьюсь головой о проблеме.

Я работаю над детской игрой (flash as3), в которой ребенку читают рассказы, стихи, песни и т. Д. Есть голосовая запись чтения / пения текста, текст выделяется, когда слова произносятся / поются. Ребенок может самостоятельно включать и выключать подсветку голоса и слова. Ребенок также может сделать собственную запись. Сейчас говорит, что запись работает нормально. Я могу снять его с микрофона, и ребенок может воспроизвести его без проблем.

Проблема заключается в том, что клиент хочет, чтобы ребенок мог сохранить эту запись на веб-сервере.

Мне показалось, что проблема решена с помощью объекта URLRequest и URLLoader. MP3 обнаруживался в указанной папке на веб-сервере. Я играл в нее с помощью медиаплеера, и это сработало. Ребенок также может загрузить указанный файл без проблем.

ТОГДА, когда я попробовал это через браузер (вместо флеш-плеера), я получил страшную ошибку песочницы. Единственный способ, которым такая операция с указанными объектами может происходить в среде браузера, - это если пользователь инициируется через диалоговое окно. Об этом говорили дети, и мы все равно не экономим на месте.

Ребенку предоставляется 3 слота сохранения, по которым они щелкают (WSprites). Что технически инициируется пользователем, но Flash не может этого знать. 3 слота сохранения содержат звуки в памяти и изменяются только тогда, когда пользователь записывает или загружает. Когда пользователь сохраняет, его отправляют на php для сохранения.

Теперь я попытался использовать js в качестве посредника, но в итоге я потерял свои байты, и мои js и php, вероятно, самые слабые области всех моих навыков программирования.

У меня вопрос: знает ли кто-нибудь способ отправки байтового массива в php без установки песочницы. (желательно без JS, но если мне нужно, я должен)

Ниже приведен скрипт php:

<?php

    $default_path = 'images/';

    // check to see if a path was sent in from flash //
    $target_path = ($_POST['dir']) ? $_POST['dir'] : $default_path;
    if (!file_exists($target_path)) mkdir($target_path, 0777, true);

    // full path to the saved image including filename //
    $destination = $target_path . basename( $_FILES[ 'Filedata' ][ 'name' ] ); 


    // move the image into the specified directory //
    if (move_uploaded_file($_FILES[ 'Filedata' ][ 'tmp_name' ], $destination)) {
      echo "The file " . basename( $_FILES[ 'Filedata' ][ 'name' ] ) . " has been uploaded;";
    } else {
        echo "FILE UPLOAD FAILED";
    }
?>

Ниже приведен метод as3, который взаимодействует с ним:

public function save(slotNum:uint, byteArray:ByteArray, fileName:String, 
                     $destination:String = null, $script:String=null, 
                 parameters:Object = null):void
{
//trace("this happens"); //debug                

_curRecordSlot = slotNum; //set slot number
_recorder = _recordSlots[_curRecordSlot]; //set recorder to new slot
_saveFileName = "recording" + _curRecordSlot.toString() + ".mp3"; //set recording file name         

var i: int;
var bytes:String;

var postData:ByteArray = new ByteArray();
postData.endian = Endian.BIG_ENDIAN;

var ldr:URLLoader = new URLLoader(); //instantiate a url loader
ldr.dataFormat = URLLoaderDataFormat.BINARY; //set loader format

_request = new URLRequest(); //reinstantiate request
_request.url = $script; //set path to upload script

//add Filename to parameters
if (parameters == null) 
{
    parameters = new Object();
}
parameters.Filename = fileName;

//add parameters to postData
for (var name:String in parameters) 
{
    postData = BOUNDARY(postData);
    postData = LINEBREAK(postData);
    bytes = 'Content-Disposition: form-data; name="' + name + '"';
    for ( i = 0; i < bytes.length; i++ ) 
    {
        postData.writeByte( bytes.charCodeAt(i) );
    }
    postData = LINEBREAK(postData);
    postData = LINEBREAK(postData);
    postData.writeUTFBytes(parameters[name]);
    postData = LINEBREAK(postData);
}

//add img destination directory to postData if provided //
if ($destination)
{    
    postData = BOUNDARY(postData);
    postData = LINEBREAK(postData);
    bytes = 'Content-Disposition: form-data; name="dir"';
    for ( i = 0; i < bytes.length; i++ ) 
    {
        postData.writeByte( bytes.charCodeAt(i) );
    }
    postData = LINEBREAK(postData);
    postData = LINEBREAK(postData);
    postData.writeUTFBytes($destination);
    postData = LINEBREAK(postData);
}

//add Filedata to postData
postData = BOUNDARY(postData);
postData = LINEBREAK(postData);
bytes = 'Content-Disposition: form-data; name="Filedata"; filename="';
for ( i = 0; i < bytes.length; i++ ) 
{
    postData.writeByte( bytes.charCodeAt(i) );
}
postData.writeUTFBytes(fileName);
postData = QUOTATIONMARK(postData);
postData = LINEBREAK(postData);
bytes = 'Content-Type: application/octet-stream';
for ( i = 0; i < bytes.length; i++ ) 
{
    postData.writeByte( bytes.charCodeAt(i) );
}
postData = LINEBREAK(postData);
postData = LINEBREAK(postData);
postData.writeBytes(byteArray, 0, byteArray.length);
postData = LINEBREAK(postData);

//add upload file to postData
postData = LINEBREAK(postData);
postData = BOUNDARY(postData);
postData = LINEBREAK(postData);
bytes = 'Content-Disposition: form-data; name="Upload"';
for ( i = 0; i < bytes.length; i++ ) 
{
    postData.writeByte( bytes.charCodeAt(i) );
}
postData = LINEBREAK(postData);
postData = LINEBREAK(postData);
bytes = 'Submit Query';
for ( i = 0; i < bytes.length; i++ ) 
{
    postData.writeByte( bytes.charCodeAt(i) );
}
postData = LINEBREAK(postData);

//closing boundary
postData = BOUNDARY(postData);
postData = DOUBLEDASH(postData);        

//finally set up the urlrequest object //
_request.data = postData;
_request.contentType = 'multipart/form-data; boundary=' + _boundary;
_request.method = URLRequestMethod.POST;
_request.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );

//add listener to listen for completion
      ldr.addEventListener(Event.COMPLETE, onSaveComplete, false, 0, true); 
//add listener for io errors
      ldr.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
//add listener for security errors
      ldr.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError, false, 
                           0, true);
ldr.load(_request); //load the file 
}

Приведенный выше код прекрасно работает во флеш-плеере, но вызывает ошибку песочницы в браузере.

Edit:

В соответствии с моей просьбой, вот мой код для встраивания (я заменил любое место с названием игры на TITLEOFGAME):

<html lang="en">
<head>
<meta charset="utf-8"/>
<title>TITLEOFGAME</title>
<meta name="description" content="" />

<script src="js/swfobject.js"></script>
<script>
    var flashvars = {
    };
    var params = {
        menu: "false",
        scale: "noScale",
        allowFullscreen: "true",
        allowScriptAccess: "always",
        bgcolor: "",
        wmode: "direct" // can cause issues with FP settings & webcam
    };
    var attributes = {
        id:"TITLEOFGAME"
    };
    swfobject.embedSWF(
        "Hub.swf", 
        "altContent", "900", "506", "10.0.0", 
        "expressInstall.swf", 
        flashvars, params, attributes,
        {name:"TITLEOFGAME"}
    );
</script>       

<style>
    html, body { height:100%; overflow:hidden; }
    body { margin:0; }
</style>
</head>
<body>
<div id="altContent">
    <h1>TITLEOFGAME</h1>
    <p><a href="http://www.adobe.com/go/getflashplayer">Get Adobe Flash 
                player</a></p> //this line was just moved down for limitations text input for 
                               //this post
</div>
</body>
</html>

Ответы [ 2 ]

1 голос
/ 03 февраля 2012

Это спрашивали раньше

Кажется, это может быть тип контента или потеря события мыши в стеке.

Очевидно, это происходит только в том случае, если URLLoader POST содержит атрибут «filename» в заголовке Content-Disposition.
bytes = 'Content-Disposition: form-data; name="Filedata"; filename="'; Попробуйте кодирование base64 и отправку в виде строки, чтобы обойти это.

[EDIT]
Я предполагаю, что вот код обидчика.

bytes = 'Content-Disposition: form-data; name="Filedata"; filename="';
for ( i = 0; i < bytes.length; i++ ) 
{
    postData.writeByte( bytes.charCodeAt(i) );
}

Если у вас есть Content-Disposition с данными формы и именем файла, это вызовет ошибку безопасности.
Данные формы с файлом в ней можно отправлять только при взаимодействии пользователя (например, щелчок мышью) в стеке.
При этом необходимо удалить Content-Disposition: form-data; Name = "FILEDATA"; filename = "'и замените его строкой.
Лично я бы поцарапал этот метод. Разработчик явно не тестировал этот код в производственной среде.

// disclaimer none of this code is tested as I pretty much just wrote it.
// however it should at least compile and you should be able to get a little idea of whats going on

// first create the endoder
var encoder:Base64Encoder = new Base64Encoder( )

// now encode the bytearray
    encoder.encodeBytes( byteArrayToEncode )

// get the encoded data as a string
var myByteArrayString:String = encoder.toString()

// lets verify the data should see a sting with base64 characters
trace( "show me the string->" + myByteArrayString )

// create the variables object that we want to POST to the server
var urlVars:URLVariables = new URLVariables();

// assign the base64 encoded bytearray to the POST variable of your choice here is use "data"
    urlVars.data = myByteArrayString;

// create the request object with the url you are sending the data to
var request:URLRequest = new URLRequest( 'Url of the PHP page below' ); 

// assign the POST data to the request
    request.data = urlVars

// just making sure POST method is being used
    request.method = URLRequestMethod.POST;

// here we make a loader even though it is a loader it can be used to send POST data along with the request to a page to load
var urlLoader:URLLoader = new URLLoader();

// just making sure the server knows we are sending data as a string
    urlLoader.dataFormat = URLLoaderDataFormat.TEXT;

// create your call back functions of your choice
 //   urlLoader.addEventListener(Event.COMPLETE, recievedData );
 //   urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler );
 //   urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler );

// wrap the load in a try catch because we are special
try {
// load the request object we just created
  urlLoader.load( request );
} catch (e:Error) {
  trace(e);
}

Трасса должна выводить что-то вроде этого dG8gQ29udmVydA ==, за исключением того, что гораздо более длинные знаки равенства в конце строки являются заполнителями, поэтому это должно дать вам подсказку, если данные преобразованы правильно. Обратите внимание, что строка состоит из буквенно-цифровых символов.
С тех пор, как вы новичок в byteArray, я бы посоветовал немного погуглить по нему сегодня вечером в свободное время и попытаться понять, что это такое и как оно работает.

<?php

$decodedData= null;

if (!empty($_POST['data'])){
  // here is your data in pre-encoded format do what you want with it
  $decodedData= base64_decode( $_POST['data'] );
  file_put_contents("test.txt",$decodedData);

}

?>
0 голосов
/ 03 февраля 2012

Вы можете отправить свои записанные данные в приложение на стороне сервера в виде массива байтов, и байты будут сохранены в соответствии с требуемым форматом, таким как flv или любой другой файл (только поддерживаемый формат). Проверьте это с помощью AMFPHP, PHP и сохранения байтового массива с использованием PHP и ActionScript 3.0. Вы получите пример этого. Пожалуйста, проверьте эту ссылку для записи и преобразования аудио в массив байтов: Нажмите здесь

...