我正在尝试使用FTP上传一个zip文件,当文件大小小于400 KB正确上传时,当它超过400 KB时,只上传了414 KB并且结果文件已损坏。 我从Windows尝试了相同的代码,它适用于各种规模。
这是我的代码:
public function uploadZipFile() {
//Socket instance which will be used to connect to ftp server
s.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
s.addEventListener(ProgressEvent.SOCKET_DATA, onReturnData);
s.addEventListener(Event.CONNECT, onConnectHandler);
s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
//
//Socket instance which will be used to connect to receive data sent by ftp server
r.addEventListener(ProgressEvent.SOCKET_DATA, onServData);
r.addEventListener(Event.CONNECT, onPasvConn);
r.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
dtimer = new Timer(10,1);
dtimer.addEventListener(TimerEvent.TIMER_COMPLETE,function(){checkForStream();});
this.addEventListener('dataReceived',onDataReceived);
var file:File = new File("XXX.zip");
initUpload(file)
}
private function onReturnData(evt:ProgressEvent)
{
var d = s.readUTFBytes(s.bytesAvailable);
trace(d);
//check here for complete list of return codes and their meaning
//- http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
// the return message will have a 3 digit return code followed by a space and related message
// if the 3 digit return code is followed by "-" the it will be a multiline message
//-wait until the line with 3 digit code followed by space is delivered
if(d.indexOf("220 ")>-1){
//connected to ftp server send user name to server
s.writeUTFBytes("USER "+ftp_username+"\n");
s.flush()
}
if(d.indexOf("331 ")>-1){
//Username accepted now send password to server
s.writeUTFBytes("PASS "+ftp_password+"\n");
s.flush()
}
if (d.indexOf("230") > -1 && d.indexOf("OK.") > -1)
{
//Password accepted - lets enter passive mode and retrieve a list of files from a directory
//first enter passive mode
trace("Log in successful!");
s.writeUTFBytes("PASV \n");
s.flush();
}
var a = d.indexOf('227');
if (a > -1)
{
//Entering passive mode message will be returned along with it details of ip and port address will be returned
//-we have to connect to that address to receive the data
//format of the message will be: 227 Entering Passive Mode (209,190,85,253,148,206)
//the data inside brackets is the ip and port address, first four numbers represent IP and last 2 PORT
//the port value have to be calculated by multiplying the 5th number with 256 and adding the 6th number to it
//here in this example IP is 209.190.85.253 , PORT is (148*256)+206 = 38094
var st = d.indexOf("(",a);
var en = d.indexOf(")",a);
var str;
str = d.substring(st + 1,en);
var a2 = str.split(",");
var p1 = a2.pop();
var p2 = a2.pop();
var ip:String = a2.join(".");
var port:int=(p2*256)+(p1*1);
r.connect(ip, port);
}
if(d.indexOf("226 ")>-1){
//Data Transfer completely lets disconnect from server
if (process=='download')
{
trace("DOWNLOAD_COMPLETE");
}
if (process=='upload')
{
trace("UPLOAD_COMPLETE");
informServer();
}
dispatchEvent(new Event("dataReceived"))
}
if(d.indexOf("221 ")>-1){
//LOGGED OUT from server
}
if (d.indexOf("150 ") > -1)
{
if (process == 'upload')
{
//Once data connection is established we can start sending the data to the server
startSendingData();
}
}
}
private function onConnectHandler(evt:Event)
{
trace("CONNECTED TO FTP SERVER");
//Client has connected to ftp server
//you can also send multiple commands at same time like below or send step by step based on return code
//-!
//s.writeUTFBytes("USER username\n");
//s.writeUTFBytes("PASS password\n");
//s.flush();
}//
private function onPasvConn(evt:Event):void
{
trace("CONNECTED TO DATA PORT");
//Now send LIST command to retrieve directory listings
if (process == 'getDirList')
{
//To retrive directory listings send following command
s.writeUTFBytes("LIST "+remoteFolderStr+"\n");
}
else if (process=='download')
{
//To Download a file send following command
//RETR is the command followed by a space and path to file in remote server
s.writeUTFBytes("RETR "+remoteFolderStr+"/"+remoteFile+"\n");
}
else if (process=='upload')
{
//To Upload a file send following command
//STOR is the command followed by a space and path wher to store the file in remote server
//-with the name of the file to be saved as..you can provide any name with extension
s.writeUTFBytes("STOR /"+localFile.name+"\n");
}
s.flush();
}
private function onServData(evt:ProgressEvent):void
{
//DATA RECEIVED FROM SERVER THRO DATA PORT
var d = r.readUTFBytes(r.bytesAvailable);
if (process == 'getDirList')
{
d = r.readUTFBytes(r.bytesAvailable);
trace(d);
}
else if (process=='download')
{
//As the data connection is established start writing the data to the fileStream
fileData = new ByteArray();//temporary bytearray object to write the incoming data
r.readBytes(fileData, 0, r.bytesAvailable);//write data to the temp bytearray
fileStream.writeBytes(fileData, 0, fileData.bytesAvailable);//now write the bytearray to file stream
//instead you can directly write the data to file stream drom socket
}
}
private function onIOERR(evt:IOErrorEvent):void
{
trace(evt.errorID+":"+evt.text);
}
private function checkForStream():void
{
//this function is used to check if the incoming data is fully written to the filestream and then close the filestream
//-even if the ftp server dispatches that the file has been transfered...you application cn be still writing them to the filestream
if(!r.connected){
fileStream.close()
}else{
//if the file is still been writing restart the timer
dtimer.reset()
dtimer.start()
}
}
//
public function initUpload(fileToUpload:File):void
{
//called when upload event is triggered
localFile = fileToUpload;
if (localFile.exists)
{
// this.remoteFolderStr=remote_folder.text
startUploadProcess();
}
}
private function startUploadProcess():void
{
//create and open a fileStream
fileStream=new FileStream();
fileStream.open(localFile, FileMode.READ);
process = "upload";
fileData = new ByteArray();
//You need to pass this command 'TYPE I' to set data transfer mode as binary
s.writeUTFBytes("TYPE I\n");
s.writeUTFBytes("PASV \n");
s.flush();
}
private function startDownloadProcess():void
{
localFile = localFolder.resolvePath(remoteFile);
fileStream=new FileStream();
fileStream.open(localFile, FileMode.WRITE);
process = "download";
fileData = new ByteArray();
s.writeUTFBytes("TYPE I\n");
s.writeUTFBytes("PASV \n");
s.flush();
}
private function startSendingData():void
{
interval = setInterval(sendData,300);
}
private function sendData():void
{
//file to be uploaded is sent as binary data
if (fileStream.bytesAvailable <= 0)
{
clearInterval(interval);
r.close();
return;
}
if (fileStream.bytesAvailable < bufferSize)
{
bufferSize = fileStream.bytesAvailable;
}
var ba:ByteArray = new ByteArray();
fileStream.readBytes(ba, 0, bufferSize);
r.writeBytes(ba, 0, ba.bytesAvailable);
r.flush();
}
private function onDataReceived(evt:Event):void
{
if(process=='download'){
dtimer.start();
}
}
答案 0 :(得分:0)
如果有人遇到此问题,我使用小bufferSize
解决了这个问题,我将其设置为100KB
,
我发现在缓冲区很大的时候发送所有数据之前都会尝试关闭连接。
答案 1 :(得分:0)
您可以添加事件OutputProgressEvent.OUTPUT_PROGRESS以检查已在dataChannelConnection中写入的字节数。