原文地址:http://www.pavlasek.sk/devel/?p=10
In Flash player it was possible until version 10 to upload files only by FileReference.upload method (there were some ugly hacks – such as uploading in external iframe).
Uploading files using directly FileReference.upload has some serious problems problems. Especially on Firefox, Flash player plugin creates it’s own request (different UserAgent, session and so) so on server it is handled in different session. All the parameters has to be sent, or some hacks has to be done (I manually set the jsessionid to each request).
And after all known hacks, it has still some serious problems using SSL – if the certificate is not validly imported to client machine, it just crashes without asking, if it has to trust it and so. See bugs:
Since v. 10 (and Flex 4), there is possibility to read local files directly, so I decided to try to upload files not using FileReference.upload method. But to read data as ByteArray and send it as POST request to server.
I found interesting class -UploadPostHelper in this article . Next I merged that example with my old code – browse for file and changed the method from FileReference.upload to FileReference.load . Server is java servlet using apache commons FileUpload – saves file to temp folder and sends XML response – all form items from post request and file uploaded – name and absolute path.
Adobe has changed security in flash player 10, it is impossible to send files in background (probably all requests now needs user interaction). It has to be in some user-action (click…) event handler, so I have two buttons, one for browse for a file, one for upload. Using just method that handles Event.COMPLETE (FileReference) causes Security sandbox violation .
Here is my Client code (UploadTest.mxml):
import mx.controls.Alert; static public const SERVER_URL:String = "http://localhost:8081/flash10upload/servlet/FlexUpload"; private var fileReference:FileReference = new FileReference(); private function onLoad():void { fileReference = new FileReference(); var myFilter:FileFilter = new FileFilter("Text","*.txt"); fileReference.browse([myFilter]); fileReference.addEventListener(Event.SELECT,onFileSelect); fileReference.addEventListener(Event.COMPLETE,onFileComplete); } private function onFileSelect(event:Event):void { fileReference.load(); } private function onFileComplete(event:Event):void { Alert.show("File Loaded, click upload..."); uploadBtn.enabled = true; } private function upload():void { var byteArray:ByteArray = new ByteArray(); var fileName:String = fileReference.name; var uploadPath:String = SERVER_URL; var parameters:Object = new Object(); parameters.test = "test1"; fileReference.data.readBytes(byteArray,0,fileReference.data.length); var urlRequest:URLRequest = new URLRequest(); urlRequest.url = uploadPath; urlRequest.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary(); urlRequest.method = URLRequestMethod.POST; urlRequest.data = UploadPostHelper.getPostData(fileName, byteArray, parameters); urlRequest.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) ); var urlLoader:URLLoader = new URLLoader(); urlLoader.dataFormat = URLLoaderDataFormat.BINARY; urlLoader.addEventListener(Event.COMPLETE, onComplete); urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError); urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError); urlLoader.load(urlRequest); } private function onComplete(eventObj:Event):void { var ldr:URLLoader = eventObj.currentTarget as URLLoader; Alert.show(ldr.data , "complete"); } private function onError(eventObj:ErrorEvent):void { Alert.show("onError"); }
Here is my Server code (FlexUploadServlet):
package sk.pavlasek.flash10Upload.web; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.log4j.Logger; public class FlexUploadServlet extends HttpServlet { private static final long serialVersionUID = 4588660828164350807L; private static final Logger log = Logger.getLogger(FlexUploadServlet.class); public void doPost(HttpServletRequest req, HttpServletResponse res) throws UnsupportedEncodingException { res.setDateHeader("Expires", -1); res.setDateHeader("Last-Modified", System.currentTimeMillis()); res.setHeader("Pragma", ""); res.setHeader("Cache-Control", ""); req.setCharacterEncoding("UTF-8"); res.setCharacterEncoding("UTF-8"); File disk = null; FileItemFactory factory = new DiskFileItemFactory(); List items = null; ServletFileUpload upload = new ServletFileUpload(factory); ServletOutputStream out = null; try { res.setContentType("text/xml"); out = res.getOutputStream(); out.println(""); items = upload.parseRequest(req); for (FileItem item : items) { if (item.isFormField()) { out.println(" + "\" value=\"" + item.getString() + "\" />"); } else { String tempdir = System.getProperty("java.io.tmpdir"); if (!(tempdir.endsWith("/") || tempdir.endsWith("\\"))) { tempdir = tempdir + System.getProperty("file.separator"); } String fileName = tempdir + item.getName(); disk = new File(fileName); item.write(disk); log.debug(disk.getAbsolutePath()); out.println(""); out.println("" + item.getName() + ""); out.println("" + disk.getAbsolutePath() + ""); out.println(""); } } out.println(""); out.close(); } catch (FileUploadException fue) { fue.printStackTrace(); } catch (IOException ioe) { ioe.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }