Is anybody out there having any problems with opening a write stream connected to an FTP server? I can get a directory listing fine, but the code which has been working to create and open a CFWriteStreamRef is failing when trying to write to a local directory from an ftp server.
It worked fine until OS4.0 and it also works on the 4.0 simulator.
Code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documents = [[paths objectAtIndex:0] stringByAppendingString:@"/Inbox/"];
NSMutableArray *files_to_download = [[NSMutableArray alloc] init]; //stores files
NSString *downloadAddress = @"ftp://><an address>/Downloads/";
//try and get listing
Boolean status = MySimpleDirectoryListing((CFStringRef)downloadAddress, CFSTR("userName"), CFSTR("password"));
//***Works Fine and Returns Listing***
if (!status) NSLog(@"(MySimpleDirectoryListing) ERROR: failed to connect");
if (status) CFRunLoopRun();
NSInteger i = 0;
NSInteger count = files_to_download.count;
for(i;i<count;i++)
{
//be sure to append the directory and the filename to the address.
NSString *address = [@"ftp://><an address>/" stringByAppendingString:[@"/Downloads/" stringByAppendingString:(NSString *)[files_to_download objectAtIndex:i]]];
NSURL *u = [[NSURL alloc] initFileURLWithPath:documents];
status = iDownload((CFStringRef)address, (CFURLRef)u, CFSTR("userName"), CFSTR("password"));
[u release];
if (!status) NSLog([@"(iDownload) ERROR: failed to download " stringByAppendingString:address]);
if (status) CFRunLoopRun();
}
Code:
static Boolean
iDownload(CFStringRef urlString, CFURLRef destinationFolder, CFStringRef username, CFStringRef password)
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamClientContext context = { 0, NULL, NULL, NULL, NULL };
CFURLRef downloadPath, downloadURL;
CFStringRef fileName;
Boolean success = true;
iStreamInfo *streamInfo;
downloadURL = CFURLCreateWithString(kCFAllocatorDefault, urlString, NULL);
/* Copy the end of the file path and use it as the file name. */
fileName = CFURLCopyLastPathComponent(downloadURL);
assert(downloadURL != NULL);
/* Create the downloadPath by taking the destination folder and appending the file name. */
downloadPath = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, destinationFolder, fileName, false);
CFRelease(fileName);
assert(downloadPath != NULL);
/* Create a CFWriteStream for the file being downloaded. */
writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, downloadPath);
CFRelease(downloadPath);
assert(writeStream != NULL);
/* CFReadStreamCreateWithFTPURL creates an FTP read stream for downloading from an FTP URL. */
readStream = CFReadStreamCreateWithFTPURL(kCFAllocatorDefault, downloadURL);
CFRelease(downloadURL);
assert(readStream != NULL);
iStreamInfoCreate(&streamInfo, readStream, writeStream);
context.info = (void *)streamInfo;
success = CFWriteStreamOpen(writeStream);
if (success) {
//read the stream using callback
}
else {
fprintf(stderr, "CFWriteStreamOpen failed\n");
iStreamInfoDestroy(streamInfo);
}
return success;
}
Code:
#define kMyBufferSize 32768
typedef struct iStreamInfo {
CFWriteStreamRef writeStream;
CFReadStreamRef readStream;
SInt64 fileSize;
UInt32 totalBytesWritten;
UInt32 leftOverByteCount;
UInt8 buffer[kMyBufferSize];
CFDictionaryRef proxyDict;
} iStreamInfo;
static void
iStreamInfoCreate(iStreamInfo ** info, CFReadStreamRef readStream, CFWriteStreamRef writeStream)
{
iStreamInfo * streamInfo;
streamInfo = malloc(sizeof(iStreamInfo));
streamInfo->readStream = readStream;
streamInfo->writeStream = writeStream;
streamInfo->fileSize = 0;
streamInfo->totalBytesWritten = 0;
streamInfo->leftOverByteCount = 0;
*info = streamInfo;
}