Показать сообщение отдельно
Старый 31.10.2008, 18:27
NewFolder вне форума Посмотреть профиль Отправить личное сообщение для NewFolder Найти все сообщения от NewFolder
  № 1  
Ответить с цитированием
NewFolder
 
Аватар для NewFolder

Регистрация: Nov 2006
Сообщений: 155
По умолчанию Посылка файлов на сервер

Эта тема очень часто поднимается на форумах. Почти все советуют способ, при котором на сервер посылается один файл, а на сервере его можно считать только используя $GLOBALS['HTTP_RAW_POST_DATA']. Это довольно таки не удобно. А что если мне нужно отослать несколько файлов сразу?
Немного погуглил и нашёл класс UploadPostHelper. Он отсылает тоже один файл на сервер, но к нему уже можно обращаться через массив $_FILES. Добавил возможность отсылать несколько файлов, предварительно пофиксив в нем глюк. Теперь мы можем отсылать сколько угодно файлов одним запросом и обращаться к ним обычным нам способом.
Пользуйтесь на здоровье!

Сам класс
Код:
package {

	import flash.events.*;
	import flash.net.*;
	import flash.utils.ByteArray;
	import flash.utils.Endian;

	/**
	 * Take a fileName, byteArray, and parameters object as input and return ByteArray post data suitable for a UrlRequest as output
	 *
	 * @see http://marstonstudio.com/?p=36
	 * @see http://www.w3.org/TR/html4/interact/forms.html
	 * @see http://www.jooce.com/blog/?p=143
	 * @see http://www.jooce.com/blog/wp%2Dcontent/uploads/2007/06/uploadFile.txt
	 * @see http://blog.je2050.de/2006/05/01/save-bytearray-to-file-with-php/
	 *
	 * @author Jonathan Marston
	 * @version 2007.08.19
	 *
	 * This work is licensed under a Creative Commons Attribution NonCommercial ShareAlike 3.0 License.
	 * @see http://creativecommons.org/licenses/by-nc-sa/3.0/
	 *
	 */
	public class UploadPostHelper {

		/**
		 * Boundary used to break up different parts of the http POST body
		 */
		private static var _boundary:String = "";
		
		private static var files:Array = [];

		/**
		 * Get the boundary for the post.
		 * Must be passed as part of the contentType of the UrlRequest
		 */
		public static function getBoundary():String {

			if(_boundary.length == 0) {
				for (var i:int = 0; i < 0x20; i++ ) {
					_boundary += String.fromCharCode( int( 97 + Math.random() * 25 ) );
				}
			}

			return _boundary;
		}

		/**
		 * Create post data to send in a UrlRequest
		 */
		public static function attachFile(fileName:String, byteArray:ByteArray, parameters:Object = null) {

			var i: int;
			var bytes:String;

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

			//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 Filedata to postData
			postData = BOUNDARY(postData);
			postData = LINEBREAK(postData);
			bytes = 'Content-Disposition: form-data; name="' +fileName+ '"; 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 filed 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);

			files.push(postData);
		}

		public static function getPostData():ByteArray {
			var postData:ByteArray = new ByteArray();
			postData.endian = Endian.BIG_ENDIAN;
			
			for (var i:int = 0; i < files.length; i++){
				postData.writeBytes(files[i], 0, files[i].length);
			}
			postData = DOUBLEDASH(postData);
			return postData;
		}
		
		public static function reset():void{
			files = [];
		}
		
		/**
		 * Add a boundary to the PostData with leading doubledash
		 */
		private static function BOUNDARY(p:ByteArray):ByteArray {
			var l:int = UploadPostHelper.getBoundary().length;

			p = DOUBLEDASH(p);
			for (var i:int = 0; i < l; i++ ) {
				p.writeByte( _boundary.charCodeAt( i ) );
			}
			return p;
		}

		/**
		 * Add one linebreak
		 */
		private static function LINEBREAK(p:ByteArray):ByteArray {
			p.writeShort(0x0d0a);
			return p;
		}

		/**
		 * Add quotation mark
		 */
		private static function QUOTATIONMARK(p:ByteArray):ByteArray {
			p.writeByte(0x22);
			return p;
		}

		/**
		 * Add Double Dash
		 */
		private static function DOUBLEDASH(p:ByteArray):ByteArray {
			p.writeShort(0x2d2d);
			return p;
		}

	}
}
Пример использования
Код:
//Reset uploader object
UploadPostHelper.reset();
			
//Get url and set post data
var url_request:URLRequest = new URLRequest("script url");			
			
url_request.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
url_request.method = URLRequestMethod.POST;			
			
for (var i:int = 0; i < frames.length; i++){
    //UploadPostHelper.attachFile(имя файла, ByteArray);
    UploadPostHelper.attachFile("file" + i.toString(), frames[i]);				
}
						
url_request.data = UploadPostHelper.getPostData();
trace("Pack size: " + url_request.data.length);

//Send images to the server
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, serverResult);
loader.addEventListener(IOErrorEvent.IO_ERROR, serverResult);
loader.load(url_request);
__________________
Нет ничего невозможного