flash上传在spring mvc中出现的问题2

转载请注明: TheViper http://www.cnblogs.com/TheViper 

这两天本屌在做flash拼图上传遇到点坑

上传原理很简单,就是把上图右边画布区域BitmapData.draw()画下来,然后用as3corelib的JPGEncoder将BitmapData编码成ByteArray,ByteArray就是要上传的图片数据。然后

            var req:URLRequest = new URLRequest("http://localhost:8080/qzone/photo/upload1?width=555&height=420");
            req.data = Data;
            req.method = URLRequestMethod.POST;
            loader = new URLLoader();
            loader.dataFormat = URLLoaderDataFormat.BINARY;
            loader.load(req);
            loader.addEventListener(Event.COMPLETE, upload_complete);

由于传的是ByteArray 对象的二进制数据,后台注入MultipartFile

    public @ResponseBody String upload1(MultipartFile filedata,HttpServletRequest request,
            HttpSession session)throws JSONException,IOException{
            ............
    }

可以看到这里首先是不能decode解码,然后是请求的content-type不是multipart.

先说解码问题,很容易想到用Base64编码图片,把编码成的字符串当成请求的参数值传给后台。

            var req:URLRequest = new URLRequest("http://localhost:8080/qzone/photo/upload");
            var variables:URLVariables = new URLVariables();
            variables.name ='puzzle_image.jpeg';
            variables.imgData =base64String;
            variables.width =555;
            variables.height =420;
            req.data = variables;

后台取出请求中的imgData参数,解码,写入文件就可以了。

而actionscript3 Base64编码要用到mx.utils包里的Base64Encoder类,这个是flex里面的,不过可以从flex里面取出来作为独立的类使用。附上下载api.

使用时注意不能看到api里面的

就直接

            new Base64Encoder().encodeBytes(Data);
            variables.imgData =Data;

后面还写着Encodes a ByteArray in Base64 and adds the result to an internal buffer. Subsequent calls to this method add on to the internal buffer. After all data have been encoded, call toString() to obtain a Base64 encoded String.

意思是Base64编码后的字符串在Base64Encoder类里面,需要通过toString()方法去取,具体的

            var b64:Base64Encoder = new Base64Encoder();
            b64.encodeBytes(Data);
            variables.imgData =b64.toString();

这里其实已经把问题解决了,但是本屌还是要画蛇添足,试试从上面的第二个问题入手,解决图片不能上传的问题。

先试试把请求的content-type设为multipart/form-data。

            var req:URLRequest = new URLRequest("http://localhost:8080/qzone/photo/upload1?width=555&height=420");
            req.data = Data;
            req.method = URLRequestMethod.POST;
            req.contentType="multipart/form-data";

这时会出现错误org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found。

这个平时没注意到,原来还要向post体内加东西才能让后台正确解析post里的二进制数据。比如

这里用到UploadPostHelper.as。

package utils
{
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.utils.*;
    public class UploadPostHelper
    {

        private static var _boundary:String = "";

        /**
         * 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 getPostData(fileName:String, byteArray:ByteArray, parameters:Object = null):ByteArray
        {

            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="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 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);

            return postData;
        }

        //--------------------------------------
        //  EVENT HANDLERS
        //--------------------------------------

        //--------------------------------------
        //  PRIVATE & PROTECTED INSTANCE METHODS
        //--------------------------------------

        /**
         * 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;
        }

    }

}
View Code

使用方法

            req.method = URLRequestMethod.POST;
            req.contentType="multipart/form-data; boundary="+UploadPostHelper.getBoundary();
            req.data=UploadPostHelper.getPostData(img_name,Data);

注意到UploadPostHelper.as里面bytes = 'Content-Disposition: form-data; name="Filedata"; filename="';

    public @ResponseBody String upload1(@RequestParam("Filedata") MultipartFile filedata,HttpServletRequest request,
            HttpSession session)throws JSONException,IOException{
                 ..........
    }

这里Filedata就像FileReference.upload()

是在上载传操作中位于文件数据之前的字段名.FileReference.upload()上传时,后台也应该有@RequestParam("Filedata")注解。

posted on 2015-08-20 01:21  TheViper_  阅读(772)  评论(0编辑  收藏  举报