最近開發某個專案時會用到 flash 上傳圖片的功能,
以往 flash 不管是 as2/as3 要進行上傳圖片,
都沒什麼問題,這次居然發生不能上傳的狀況,
其實之前同事也有預到過同樣的情形,
不過一忙就沒 trace 下去,
今天就徹底把問題找出來一次解決。
先描述一下此問題發生的狀況,
當使用者按下 upload 時 js 會透過 ExternalInterface 呼叫
flash function 進行上傳,就會跳出下列訊息:
SecurityError: Error #2176: 特定動作 (像是顯示彈出式視窗的動作) 只能透過使用者互動叫用,例如滑鼠按下或按下按鈕等等。
at flash.net::URLStream/load()
at flash.net::URLLoader/load()
at pages::HomePage/sendPhotoData()
at pages::HomePage/fromJs_upload()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at flash.external::ExternalInterface$/_callIn()
at Function/<anonymous>()
看這訊息,"特定動作"這到底是指什麼,我也沒開 file browse 彈出式視窗,
我只是要上傳 BitmapData....0rz
而且印象中一堆 swfupload/ajax-uploader/YUI Uploader
都用這種方式(js->flash)來上傳檔案。
請教 google 大神後發現這是 flash10 做的安全性改變,
http://www.adobe.com/devnet/flashplayer/articles/fplayer10_uia_requirements.html
其中 POST APIs 有提到以 RFC1867(Form-based File Upload) 的方式上傳,需要使用者主動 click 才有效。
那要怎麼解決呢?總不能都降回 flash9 吧~~
方法一:Base64
將圖片用 base64 編碼再用 POST 的方式送出,
缺點是 size 會變大 1/3 ,
不過目前上傳圖片都不大,這個缺點也就還能接受。
as3:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var jpegEncoder:JPGEncoder = new JPGEncoder(85); | |
var bmd:BitmapData = new BitmapData(450 , 340); | |
bmd.draw(mcBox,null,null,null,null,true); | |
var jpegBytes:ByteArray = jpegEncoder.encode(bmd); | |
var urlRequest:URLRequest = new URLRequest(); | |
urlRequest.url = "http://localhost/base64Upload.php"; | |
var variables:URLVariables = new URLVariables(); | |
variables.id = Rndm.integer(1,1000); | |
variables.file = Base64.encode(jpegBytes) | |
urlRequest.data = variables; | |
urlRequest.method = URLRequestMethod.POST; | |
var listloader:DataLoader = new DataLoader(urlRequest, { name:"myPhotoUpload", noCache:true, onComplete: onBase64DataHandler } ); | |
listloader.load(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<? | |
$id = $_POST['id']; | |
$file = $_POST['file']; | |
$target_path="./temp/".$id.".jpg"; | |
$fp = fopen($target_path, 'a'); | |
fwrite($fp, base64_decode($file)); | |
fclose($fp); | |
echo "success=true&id=".$id; | |
?> |
方法二:amf
沒錯,沒看錯,用 amf 的方式傳輸就沒這個問題,
真不曉得 adobe 在搞什麼。
不過 .Net 上的 amf 我不熟悉這邊就略過,
amfphp/zendAmf 等有時間再另開一篇來說明吧。
[update:20120606]
方法三:
避開發生問題的 request header "Content-Type" of "multipart/form-data"
as3:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var jpgencoder:JPGEncoder = new JPGEncoder(80); | |
var ba:ByteArray = jpgencoder.encode(Bitmap(_arrPhotos[0].photo).bitmapData); | |
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream"); | |
var request:URLRequest = new URLRequest("http://api.wwwins.com.tw/saveImg.php?category=" + arrSwitchBtnValue[indexSwitch]); | |
var loader:URLLoader = new URLLoader(); | |
request.requestHeaders.push(header); | |
request.method = URLRequestMethod.POST; | |
request.data = ba; | |
loader.load(request); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<? | |
$postdata = file_get_contents("php://input"); | |
if (isset($postdata)&&strlen($postdata)>0) { | |
$handle = fopen("upload/file-name.png", "w+"); | |
fwrite($handle, $postdata); | |
fclose($handle); | |
echo "r=success&category=".$_GET['category']; | |
} | |
else echo "r=error"; | |
?> |
缺點:
一次只能傳一張照片,
如果要帶參數,只能用 GET 的方式帶在 url 後面,有點小麻煩。
沒有留言:
張貼留言