iOS ftp下载远程文件夹内容(文件夹目录结构不变)
来源:互联网 发布:ubuntu安装软件 编辑:程序博客网 时间:2024/06/11 00:35
在网上搜索了一些资料下载远程文件夹及其里面的内容,然后结果都只是下载单个文件,并没有提及到下载文件夹中的东西。然后研究了下一个三方的ftp下载文件内容之后,解决了下载远程文件夹中内容的问题。
1.可以将远程文件夹的内容打包成zip的形式,然后通过下载单个文件的形式先下载到沙盒,然后解压沙盒中为zip。下载单个文件可以参照我写的http下载文件。网上也有ftp下载单个文件资料,自己查找。我用的是SSZipArchive这个三方来解压。
2.直接下载,不用压缩。用的三方是GoldRaccoon这个三方
1.)去下载三方并且导入Sources
2.)在Build Phases中添加CFNetwork和Foundation包
3.)目录结构类似这样子的
4.)我直接在Main.storyboard中添加一个button并关联成事件做点击下载用。
5.)我自己搭建的ftp服务器建立站点,下面是我服务器中的目录
目录内容:
5.)代码ViewController中的代码(代码中我已经标注了,就不再说了)
#import "ViewController.h"#import "GRRequestsManager.h"#import "GRListingRequest.h"@interface ViewController ()<GRRequestsManagerDelegate>@property (nonatomic, strong) GRRequestsManager *requestsManager;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad];}#pragma mark *** Events ***// 列表- (IBAction)respondsToListing:(UIButton *)sender { //列表localuser下的文件夹目录,这里做的只是列表目录下面有什么 [self.requestsManager addRequestForListDirectoryAtPath:@"localuser"]; [self.requestsManager startProcessingRequests];}#pragma mark *** GRRequestsManagerDelegate ***//代理方法,每次执行列表方法都会走这个方法- (void)requestsManager:(id<GRRequestsManagerProtocol>)requestsManager didCompleteListingRequest:(id<GRRequestProtocol>)request listing:(NSArray *)listing{ //沙盒目录 NSString *documentsDirectoryPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingString:@"/localuser"]; GRListingRequest *req = (GRListingRequest *)request; //远程文件夹列表 NSLog(@"%@",listing); //打印创建的目录 NSLog(@"%@",documentsDirectoryPath); NSFileManager *fileManager = [NSFileManager defaultManager]; //文件夹列表枚举 [listing enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([[obj pathExtension] isEqualToString:@""]) { //整个地址,在沙盒中创建和远程文件一样的文件夹目录 NSString *zhenggedizhi = [documentsDirectoryPath stringByAppendingString:[NSString stringWithFormat:@"%@/%@",req.path,obj]]; //如果沙盒中的这个文件夹不存在就创建 if (![fileManager fileExistsAtPath:zhenggedizhi]) { [fileManager createDirectoryAtPath:zhenggedizhi withIntermediateDirectories:YES attributes:nil error:nil]; } //然后接着递归列举文件夹下的子文件夹下的目录 [self.requestsManager addRequestForListDirectoryAtPath:[NSString stringWithFormat:@"%@%@",req.path,obj]]; [self.requestsManager startProcessingRequests]; }else{ //如果目录下的不是文件夹,则下载这个文件到沙盒的指定目录下 [self.requestsManager addRequestForDownloadFileAtRemotePath:[NSString stringWithFormat:@"%@/%@",req.path,obj] toLocalPath:[documentsDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",req.path,obj]]]; [self.requestsManager startProcessingRequests]; } }]; }#pragma mark *** Lazy loading ***- (GRRequestsManager *)requestsManager{ if (!_requestsManager) { //初始化请求类,需要ftp的地址,用户名密码 //这里是我自己在服务器上搭建了一个ftp服务器,并建立站点 _requestsManager = [[GRRequestsManager alloc]initWithHostname:@"ftp://10.185.36.12:81" user:@"zhaoqian" password:@"Zq123"]; // 设置代理 _requestsManager.delegate = self; } return _requestsManager;}@end
6.)效果
首先是列表和沙盒地址
comond+shift+g打开沙盒地址看到
也就是我下载成功了。
注意:暂时不支持中文文件名的文件下载和文件创建。有什么问题可以联系我探讨。希望对大家有帮助!
这两天解决了中文乱码的问题,ftp服务器的编码格式是gbk格式的所以要在一些地方修改
首先是包里面的内容在GRListingRequest.m中找到 case NSStreamEventEndEncountered里面的内容改为:
NSUInteger offset = 0; CFIndex parsedBytes; uint8_t *bytes = (uint8_t *)[self.receivedData bytes]; NSUInteger totalbytes = [self.receivedData length]; do { CFDictionaryRef listingEntity = NULL; parsedBytes = CFFTPCreateParsedResourceListing(NULL, &bytes[offset], totalbytes - offset, &listingEntity); if (parsedBytes > 0) { if (listingEntity != NULL) { NSDictionary *entryToAdd = [self _entryByReencodingNameInEntry: (__bridge NSDictionary *)listingEntity encoding: CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)]; self.filesInfo = [self.filesInfo arrayByAddingObject:entryToAdd]; } offset += parsedBytes; } } while (parsedBytes > 0); [self.streamInfo streamComplete:self]; break;
再在下面添加一个方法:
- (NSDictionary*)_entryByReencodingNameInEntry:(NSDictionary *)entry encoding:(NSStringEncoding)newEncoding { // CFFTPCreateParsedResourceListing always interprets the file name as MacRoman, // which is clearly bogus <rdar://problem/7420589>. This code attempts to fix // that by converting the Unicode name back to MacRoman (to get the original bytes; // this works because there's a lossless round trip between MacRoman and Unicode) // and then reconverting those bytes to Unicode using the encoding provided. NSDictionary * result; NSString * name; NSData * nameData; NSString * newName; newName = nil; // Try to get the name, convert it back to MacRoman, and then reconvert it // with the preferred encoding. name = [entry objectForKey:(id) kCFFTPResourceName]; if (name != nil) { assert([name isKindOfClass:[NSString class]]); nameData = [name dataUsingEncoding:NSMacOSRomanStringEncoding]; if (nameData != nil) { newName = [[NSString alloc] initWithData:nameData encoding:newEncoding]; } } // If the above failed, just return the entry unmodified. If it succeeded, // make a copy of the entry and replace the name with the new name that we // calculated. if (newName == nil) { // assert(NO); // in the debug builds, if this fails, we should investigate why result = (NSDictionary *) entry; } else { NSMutableDictionary * newEntry; newEntry = [entry mutableCopy]; assert(newEntry != nil); [newEntry setObject:newName forKey:(id) kCFFTPResourceName]; result = newEntry; } return result;}
其次在GRRequest.m中找到
- (NSString *)encodeString:(NSString *)string;{ NSString *urlEncoded = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes( NULL, (__bridge CFStringRef) string, NULL, (CFStringRef)@"!*'\"();:@&=+$,?%#[]%", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)); return urlEncoded;}将其改成gbk编码的格式
最后在ViewController.m中做出如下修改
添加一个解URLGBK编码的方法
- (NSString *)decodeFromPercentEscapeString: (NSString *) input{ NSMutableString *outputStr = (__bridge NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)input, CFSTR(""), kCFStringEncodingGB_18030_2000); return outputStr;}
然后将以前文件中的req.path 改为上面这个方法解码后的字符串
ViewController.m整个代码如下
#import "ViewController.h"#import "GRRequestsManager.h"#import "GRListingRequest.h"@interface ViewController ()<GRRequestsManagerDelegate>@property (nonatomic, strong) GRRequestsManager *requestsManager;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad];}#pragma mark *** Events ***// 列表- (IBAction)respondsToListing:(UIButton *)sender { //列表localuser下的文件夹目录,这里做的只是列表目录下面有什么 [self.requestsManager addRequestForListDirectoryAtPath:@"dirt"]; [self.requestsManager startProcessingRequests];}#pragma mark *** GRRequestsManagerDelegate ***//代理方法,每次执行列表方法都会走这个方法- (void)requestsManager:(id<GRRequestsManagerProtocol>)requestsManager didCompleteListingRequest:(id<GRRequestProtocol>)request listing:(NSArray *)listing{ //沙盒目录 NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSLog(@"%@",documentsDirectoryPath); GRListingRequest *req = (GRListingRequest *)request; //远程文件夹列表 NSLog(@"%@",listing); //打印创建的目录 NSFileManager *fileManager = [NSFileManager defaultManager]; //文件夹列表枚举 [listing enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([[obj pathExtension] isEqualToString:@""]) { //整个地址,在沙盒中创建和远程文件一样的文件夹目录 NSString *zhenggedizhi = [documentsDirectoryPath stringByAppendingString:[NSString stringWithFormat:@"%@%@",[self decodeFromPercentEscapeString:req.path],obj]]; //如果沙盒中的这个文件夹不存在就创建 if (![fileManager fileExistsAtPath:zhenggedizhi]) { [fileManager createDirectoryAtPath:zhenggedizhi withIntermediateDirectories:YES attributes:nil error:nil]; } //然后接着递归列举文件夹下的子文件夹下的目录 [self.requestsManager addRequestForListDirectoryAtPath:[NSString stringWithFormat:@"%@%@",[self decodeFromPercentEscapeString:req.path],obj]]; [self.requestsManager startProcessingRequests]; }else{ if ([obj isEqualToString:@"end.txt"]) { NSLog(@"finished........."); } //如果目录下的不是文件夹,则下载这个文件到沙盒的指定目录下 if (![fileManager fileExistsAtPath:[documentsDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",[self decodeFromPercentEscapeString:req.path],obj]]]) { [self.requestsManager addRequestForDownloadFileAtRemotePath:[NSString stringWithFormat:@"%@%@",[self decodeFromPercentEscapeString:req.path],obj] toLocalPath:[documentsDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",[self decodeFromPercentEscapeString:req.path],obj]]]; NSLog(@"%@",[NSString stringWithFormat:@"%@%@",[self decodeFromPercentEscapeString:req.path],obj]); [self.requestsManager startProcessingRequests]; } } }];}- (NSString *)decodeFromPercentEscapeString: (NSString *) input{ NSMutableString *outputStr = (__bridge NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)input, CFSTR(""), kCFStringEncodingGB_18030_2000); return outputStr;}#pragma mark *** Lazy loading ***- (GRRequestsManager *)requestsManager{ if (!_requestsManager) { //初始化请求类,需要ftp的地址,用户名密码 //这里是我自己在服务器上搭建了一个ftp服务器,并建立站点 _requestsManager = [[GRRequestsManager alloc]initWithHostname:@"ftp://10.185.36.12:81" user:@"zhaoqian" password:@"Zq123"]; // 设置代理 _requestsManager.delegate = self; } return _requestsManager;}@end
如果URL路劲不对会出现一个 kCFErrorDomainCFNetwork error 200的错误
- iOS ftp下载远程文件夹内容(文件夹目录结构不变)
- linux下面ftp命令下载文件夹目录
- LINUX 下载ftp文件夹下的所有内容
- C# FTP下载一目录下所有文件夹及文件
- C# FTP下载一目录下所有文件夹及文件
- ftp下载目录下所有文件及文件夹内(递归)
- linux下面ftp/wget命令下载文件夹目录
- C# 遍历FTP文件夹/下载
- linux FTP下载整个文件夹
- FTP下载文件夹到windows
- IOS 创建目录/文件夹
- CMD生成文件夹目录结构
- java展示文件夹目录结构
- CMD生成文件夹目录结构
- CMD生成文件夹目录结构
- 通过FTP方式上传文件夹(整个目录)
- 文件夹目录打包压缩下载
- FTP文件上传(自定义文件夹)、删除、下载、读取
- 多线程知识巩固(七) 多线程安全读写
- Python:文件的读取、创建、追加、删除、清空
- ReactNative开发——可触摸组件类型
- Java集合---Arrays类源码解析
- scala基础之泛型详解
- iOS ftp下载远程文件夹内容(文件夹目录结构不变)
- Sublime Text 3 快捷键精华版
- JQuery. tokenInput 解析-02 关于过滤select数据
- Kotlin让Android更简单~
- java——与c++之不同——基本类型
- 设计模式 原型设计 Prototype
- MariaDB、MySQL双主互备操作及说明
- php操作redis的方法
- Android使用MediaRecorder录音导致java.lang.RuntimeException: start failed.