Open stream error in SimpleFTPSample provided in A

2019-02-18 14:54发布

问题:

I want to upload images to server through ftp.

I found a SimpleFTPSample in apple documentation, and downloaded it.

When running the app(I'm using xcode 4.5.2, target iphone 5.0 simulator) it works fine. I'm trying to create directory in my server through this app and succeeded.

But, when uploading the image provided in the app will result in "open stream error". I didn't do any change in the app. Just typed the url,username and password. I think there is no issue with this, since, the directory which I specified was created succesfully.

While creating directory the url is "ftp://54.x.y.z/newfolder/" it is created successfully.

But, while uploading the url is "ftp://54.x.y.z/TestImage1.png"

the filepath is "/var/folders/pn/8p0jc4qn70v37j58c1kwf8l80000gn/T/TestImage1.png"

url is got by appending the last component string with the ftp url which I specified.

So, what is the mistake in it?

In the fn,

 - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
 { 



case NSStreamEventErrorOccurred: {
        [self stopSendWithStatus:@"Stream open error"];
    } break;

was called and displayed Stream open error.

I googled a whole day and no needed results. Its very urgent and I even can't start a bounty for this. Please help

回答1:

Try this....

     - (void)sendDidStart
{
    // self.statusLabel.text = @"Sending";
    [[NetworkManager sharedInstance] didStartNetworkOperation];

}

- (void)updateStatus:(NSString *)statusString
{
    assert(statusString != nil);
    //self.statusLabel.text = statusString;
}

- (void)sendDidStopWithStatus:(NSString *)statusString
{
    if (statusString == nil) {
        statusString = @"Put succeeded";
    }
    [[NetworkManager sharedInstance] didStopNetworkOperation];
}

#pragma mark * Core transfer code

// This is the code that actually does the networking.

// Because buffer is declared as an array, you have to use a custom getter.  
// A synthesised getter doesn't compile.

- (uint8_t *)buffer
{
    return self->_buffer;
}

- (BOOL)isSending
{
    return (self.networkStream != nil);
}

- (void)startSend:(NSString *)filePath
{
    BOOL                    success;
    NSURL *                 url;
    NSLog(@"localFilePathforImage..:%@",localFilePathforImage);
    assert(localFilePathforImage != nil);
    assert([[NSFileManager defaultManager] fileExistsAtPath:localFilePathforImage]);
    assert( [localFilePathforImage.pathExtension isEqual:@"png"] || [localFilePathforImage.pathExtension isEqual:@"jpg"] );

    assert(self.networkStream == nil);      // don't tap send twice in a row!
    assert(self.fileStream == nil);         // ditto

    // First get and check the URL.

    url = [[NetworkManager sharedInstance] smartURLForString:@"ftp://80.544/"];
    success = (url != nil);

    if (success) {
        // Add the last part of the file name to the end of the URL to form the final 
        // URL that we're going to put to.

        url = CFBridgingRelease(
                                CFURLCreateCopyAppendingPathComponent(NULL, ( CFURLRef) url, ( CFStringRef) imageString , false)
                                );
        success = (url != nil);
    }

    // If the URL is bogus, let the user know.  Otherwise kick off the connection.

    if ( ! success) {
        // self.statusLabel.text = @"Invalid URL";
    }    
    else 
    {

        // Open a stream for the file we're going to send.  We do not open this stream; 
        // NSURLConnection will do it for us.

        self.fileStream = [NSInputStream inputStreamWithFileAtPath:localFilePathforImage];
        assert(self.fileStream != nil);

        [self.fileStream open];

        // Open a CFFTPStream for the URL.

        self.networkStream = CFBridgingRelease(
                                               CFWriteStreamCreateWithFTPURL(NULL, ( CFURLRef) url)
                                               );
        assert(self.networkStream != nil);

        // if ([self.usernameText.text length] != 0) {
        success = [self.networkStream setProperty:@"yourusername" forKey:(id)kCFStreamPropertyFTPUserName];
        assert(success);
        success = [self.networkStream setProperty:@"password" forKey:(id)kCFStreamPropertyFTPPassword];
        assert(success);
        //}

        self.networkStream.delegate = self;
        [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [self.networkStream open];

        // Tell the UI we're sending.

        [self sendDidStart];
    }
}

- (void)stopSendWithStatus:(NSString *)statusString
{
    if (self.networkStream != nil) {
        [self.networkStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.networkStream.delegate = nil;
        [self.networkStream close];
        self.networkStream = nil;
    }
    if (self.fileStream != nil) {
        [self.fileStream close];
        self.fileStream = nil;
    }
    [self sendDidStopWithStatus:statusString];
}

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our 
// network stream.
{
#pragma unused(aStream)
    assert(aStream == self.networkStream);

    switch (eventCode) {
        case NSStreamEventOpenCompleted: {
            [self updateStatus:@"Opened connection"];
        } break;
        case NSStreamEventHasBytesAvailable: {
            assert(NO);     // should never happen for the output stream
        } break;
        case NSStreamEventHasSpaceAvailable: {
            [self updateStatus:@"Sending"];

            // If we don't have any data buffered, go read the next chunk of data.

            if (self.bufferOffset == self.bufferLimit) {
                NSInteger   bytesRead;

                bytesRead = [self.fileStream read:self.buffer maxLength:sSendBufferSize];

                if (bytesRead == -1) {
                    [self stopSendWithStatus:@"File read error"];
                } else if (bytesRead == 0) {
                    [self stopSendWithStatus:nil];
                } else {
                    self.bufferOffset = 0;
                    self.bufferLimit  = bytesRead;
                }
            }

            // If we're not out of data completely, send the next chunk.

            if (self.bufferOffset != self.bufferLimit) {
                NSInteger   bytesWritten;
                bytesWritten = [self.networkStream write:&self.buffer[self.bufferOffset] maxLength:self.bufferLimit - self.bufferOffset];
                assert(bytesWritten != 0);
                if (bytesWritten == -1) {
                    [self stopSendWithStatus:@"Network write error"];
                } else {
                    self.bufferOffset += bytesWritten;
                }
            }
        } break;
        case NSStreamEventErrorOccurred: {
            [self stopSendWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
            // ignore
        } break;
        default: {
            assert(NO);
        } break;

    }
}


回答2:

I have same issue.

This is per the hosting provider. I think the problem is that the code maybe getting confused by the "@" sign in the login name = dev@atoz.com.?

Are you using user name with @ sing ?



回答3:

Adding this line before setting the networkStream delegate in PutController.m StartSend fixed the problem for me:

[self.networkStream setProperty:(id)kCFBooleanFalse forKey:(id)kCFStreamPropertyFTPUsePassiveMode];

Without the above line (or with the property set to kCFBooleanTrue instead of kCFBooleanFalse), I consistently got Stream Open Error. I only tried with one FTP server, but it doesn't seem to support passive mode which is apparently the default.