![](/img/trans.png)
[英]Error #2044: Unhandled IOErrorEvent:. text=Error #2032: Stream Error
[英]Error #2044: Unhandled IOErrorEvent:. text=Error #2038: File I/O Error
我有一個在Flash或Flash Builder 4.5上編譯的標准AIR腳本,旨在將文件上傳到php服務器端代碼。 在完成請求之前,代碼首先將文件寫入用戶桌面。
import flash.net.*;
import flash.filesystem.*
//create the file
var file:File = File.desktopDirectory;
file = file.resolvePath("test.txt");
var fs:FileStream = new FileStream();
fs.open(file, FileMode.WRITE);
//write "test" to txt file
fs.writeUTFBytes("test");
fs.close();
//start request
var req:URLRequest = new URLRequest();
req.method = "POST";
req.url = //php file
var vars:URLVariables = new URLVariables();
vars.a = 1;
vars.b = 2;
vars.c = 3
req.data = vars;
file.upload(req, "txt_file");
現在,當我上傳到本地localhost(XAMPP)上自己的Apache測試服務器上的php文件時,文件上傳成功進行,沒有任何錯誤。 但是,當我嘗試上傳到實際服務器時,出現一個I / O錯誤:
錯誤#2044:未處理的IOErrorEvent :。 text =錯誤#2038:文件I / O錯誤。
我已經將我的max_file_size設置為2MB,所以這不是問題。 該網址也是正確的。 在查看其他來源(例如http://www.judahfrangipane.com/blog/2007/01/01/error-2044-unhandled-ioerrorevent-texterror-2038-file-io-error/ )時,有些人認為問題出在通過將目錄的.htaccess設置為以下命令來關閉Apache ModSecurity:
SecFilterEngine Off
SecFilterScanPOST Off
這是行不通的。 實際上,這使我剩下的用於從同一服務器獲取數據的代碼變得過時了。 我也知道這不是跨域問題。 我也嘗試將php代碼設置為返回HTTP200。仍然無法正常工作。 有人認為這些錯誤是隨機的,無論錯誤如何,實際的文件上傳都已經發生。 因此,可以通過僅捕獲錯誤並忽略它來解決問題( http://dev.nuclearrooster.com/2008/04/05/uploading-with-a-filereference-from-flex-3-on-os-x / )。 這不是我的選擇,因為我需要跟蹤上傳進度。
有趣的是,這似乎是Mac OSX的問題,因為我具有在Windows編譯器上運行的准確腳本,沒有錯誤,盡管唯一的規定是它們是使用較舊版本的AIR制作的。 因此,我不確定這里是否是這種情況。
我已經三天不停地撞牆了。 請幫我......
UPDATE
剛剛發現文件上傳到的服務器正在對文件上傳請求返回HTTP 301響應,這種情況再次發生在AIR的OSX上,而不是Windows或通過Firefox提交的表單數據上。
好。 這肯定是Mac OSX的問題。 由於某些原因,由OSX中File.upload()方法創建的HTTP標頭會導致外部服務器崩潰,並導致301永久移動。 在Windows中不會發生這種情況。 當然,就有關AIR編譯器而言,除HTTP 2xx響應以外的任何其他操作都會導致I / O錯誤。 因此,為了解決文件上傳問題,我們必須手動創建負責上傳本身的HTTP標頭。 我建議在此問題解決之前,不要使用File.upload()
(或FileReference.upload()
)。
為此,必須將我們上載的文件轉換為ByteArray。 因此,我只會使用File / FileReference來捕獲文件。 對於實際的上載,必須將文件轉換為ByteArray
。
在上面的示例中,這非常簡單:
import flash.net.*
import flash.utils.ByteArray;
var xml:XML = new XML(<items><item>one</item><item>two</item></items>);
var data:ByteArray = new ByteArray();
data.writeUTF(xml.toXMLString());
現在,到目前為止,創建手動HTTP標頭都歸功於Jonathan Marston( http://marstonstudio.com/2007/10/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically將jpg文件 UploadPostHelper
到服務器的三個簡單步驟/ )和他漂亮的UploadPostHelper
類:
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 = "";
/**
* 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;
}
/**
* 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;
}
}
}
現在,我們利用該類使用良好的舊URLRequest
創建我們的HTTP標頭:
var req:URLRequest = new URLRequest();
req.url = //server-side url (.php)
req.contentType = "multipart/form-data; boundary=" + UploadPostHelper.getBoundary();
req.method = URLRequestMethod.POST;
//Be sure to place the actual file name with its extension as the file name. Set the second argument as the ByteArray created earlier. Any other parameters (name-value pairs) can be added via an optional third parameter (see class above)
req.data = UploadPostHelper.getPostData("test.xml", data);
req.requestHeaders.push(new URLRequestHeader("Cache-Control", "no-cache"));
現在,不要使用File.upload()
完成請求,而只需使用URLLoader
:
var loader:URLLoader = new URLLoader();
//We have to load the data as binary as well
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, complete);
loader.addEventListener(IOErrorEvent.IO_ERROR, ioerror);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, secerror);
loader.load(req);
//Event handlers
function complete(e:Event):void {
var ba:ByteArray = e.target.data;
//Returns the XML data
trace(ba.readUTF());
}
function ioerror(e:IOErrorEvent):void {}
function secerror(e:SecurityErrorEvent):void {}
一切都應該很好地工作。 就服務器端而言,文件的名稱由上述類Filedata
定義。 一個簡單的PHP腳本來捕獲文件,如下所示:
<?php
echo file_get_contents($_FILES['Filedata']['tmp_name']);
var_dump($_FILES['Filedata']);
/*
array(1) {
["Filedata"]=>array(5) {
["name"]=>string(8) "test.xml"
["type"]=>string(24) "application/octet-stream"
["tmp_name"]=>string(38) "root/tmp/php2jk8yk"
["error"]=>int(0)
["size"]=>int(58)
}
}
*/
?>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.