// NSLog(@"%@",NSHomeDirectory()); 沙箱,存放文件的地方,输出以后 在finder中 按住shift commond+G 进入文件夹,然后看刚才的数据参数进去没有
文件管理
self.filePaths = [NSMutableArray array];
NSString *path = @"/Users/gj/Desktop/day35";
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *fileNames = [fm contentsOfDirectoryAtPath:path error:nil];
for (NSString *fileName in fileNames) {
NSString *filePath = [path stringByAppendingString:fileName];
[self.filePaths addObject:filePath];
}
//页面的显示LocalFileTableViewController 显示界面;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
NSString *filePath = self.filePaths[indexPath.row];
cell.textLabel.text = [filePath lastPathComponent];
判断一个文件是否是文件夹的判断方法
BOOL isDir;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) {
如果是文件夹,则在右边设置角标
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
cell.detailTextLabel.text = @"";
}else{
//如果是文件显示文件的大小
// 如果通过nsdata获取文件长度 需要把文件的数据先加载到内存中 才能获取长度
// NSData *data = [NSData dataWithContentsOfFile:filePath];
// fileHandle 处理文件内部数据 可以指定处理某个位置的数据
处理细节数据
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
//设置游标到某个位置
// [fileHandle seekToFileOffset:100];
从游标的位置 读取某个长度的数据
// NSData *data = [fileHandle readDataOfLength:200];
// 把游标设置到最后 并且得到文件长度
long long fileLength = [fileHandle seekToEndOfFile];
NSString *size = fileLength>1024?[NSString stringWithFormat:@"%lldKB",fileLength/1024] : [NSString stringWithFormat:@"%lldB",fileLength];
cell.detailTextLabel.text = size;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *filePath = self.filePaths[indexPath.row];
BOOL isDir;
if ([[NSFileManager defaultManager]fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) {
LocalFileTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"LocalFileTableViewController"];
vc.path = filePath;
[self.navigationController pushViewController:vc animated:YES];
}else{//如果是文件夹 就创建页面继续展开, 如果是文件就上传。。。
//拿到文件的数据;
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
self.clientSocket = [[AsyncSocket alloc]initWithDelegate:self];
//给谁发;
[self.clientSocket connectToHost:@"192.168.1.56" onPort:8800 error:nil];
[self.clientSocket writeData:fileData withTimeout:-1 tag:0];
//做到这里 仍然发布过去。因为缺少文件的头,和文件的长度,
NSString *headerString = [NSString stringWithFormat:@"upload&&%@&&%d",[filePath lastPathComponent],fileData.length];
} 到这一步,拿到了数据的字符串;
到这一步虽然将要传的文件弄出来了,但是很多地方都会用到 ,所以需要声明一个工具类,用来方便的实现这些功能
}
上一步的下一步代码
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *filePath = self.filePaths[indexPath.row];
BOOL isDir;
if ([[NSFileManager defaultManager]fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) {
LocalFileTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"LocalFileTableViewController"];
vc.path = filePath;
[self.navigationController pushViewController:vc animated:YES];
}else{
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"确定上传是吧,别后悔,大家伙都能看见" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
[alertView show];
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 1) {
//如果是文件夹 就创建页面继续展开, 如果是文件就上传。。。
//拿到文件的数据;
NSData *fileData = [NSData dataWithContentsOfFile:self.filePath];
self.clientSocket = [[AsyncSocket alloc]initWithDelegate:self];
//给谁发;
[self.clientSocket connectToHost:@"192.168.1.56" onPort:8800 error:nil];
//做到这里 仍然发布过去。因为缺少文件的头,和文件的长度,
NSString *headerString = [NSString stringWithFormat:@"upload&&%@&&%d",[self.filePath lastPathComponent],fileData.length];
NSMutableData *allData = [Utils getAllDataWithHeaderString:headerString];
[allData appendData:fileData];
[self.clientSocket writeData:allData withTimeout:-1 tag:0];
}
3.工具类中 的实现代码Utils
这个Utils的工具类里面的作用是将文件的数据集合出来 然后实现一个方法 最终方便取
#import "Utils.h"
@implementation Utils
+(NSMutableData *)getAllDataWithHeaderString:(NSString *)headerString{
//将headerString的字符串转换成 二进制数据;
// 设置一个alldata集 存放数据, 数据的长度是100;
// 然后将数据集中的数据换成 二进制数据;
NSData *headerData = [headerString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *allData = [NSMutableData dataWithLength:100];
[allData replaceBytesInRange:NSMakeRange(0, headerData.length) withBytes:headerData.bytes];
return allData;
}
@end
#import "SeversViewController.h"
#import "AsyncSocket.h"
@interface SeversViewController ()<AsyncSocketDelegate>
@property (weak, nonatomic) IBOutlet UILabel *statusLable;
@property (weak, nonatomic) IBOutlet UIProgressView *myPV;
@property (nonatomic,strong)AsyncSocket *serverSocket;
@property (nonatomic,strong)AsyncSocket *myNewSocket;
@property (nonatomic,copy)NSString *host;
@property (nonatomic,strong)NSMutableData *allData ;
@property (nonatomic,copy)NSString *fileName;
@property (nonatomic)int fileLength;
@end
@implementation SeversViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.serverSocket = [[AsyncSocket alloc]initWithDelegate:self]; //初始化服务器;
[self.serverSocket acceptOnPort:8800 error:nil];//监听端口号;
}
//正常的情况下,应该是服务器有一端,客户端一端, 这里这段代码是为了方便自己测试,服务器与客户端的状态;;;;;; 正常情况应该是点击服务器然后返回的时候服务器这个页面被干掉; 这里保留是为了方便测试
//
//-(void)viewDidDisappear:(BOOL)animated{
// self.serverSocket.delegate = nil;
//}
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{
//持有住连接进来的SOCKET 不能声明成NET开头的名字,会出错;
self.myNewSocket = newSocket;
}
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
// 链接上了就要不停的读客服端传过来的, 或者要传过来的数据;
self.host = host;//在连接成功的时候把对方的IP地址记录一下;
[self.myNewSocket readDataWithTimeout:-1 tag:0];
}
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
NSLog(@"%d",data.length);
NSData *headData = [data subdataWithRange:NSMakeRange(0, 100)];
NSString *headString = [[NSString alloc]initWithData:headData encoding:NSUTF8StringEncoding];
if (headString&&[headString componentsSeparatedByString:@"&&"].count==3) {
NSArray *headers =[headString componentsSeparatedByString:@"&&"];
NSString *type = headers[0];
if ([type isEqualToString:@"upload"]) {
self.fileName = headers[1];
self.fileLength = [headers[2]intValue];
self.statusLable.text = [NSString stringWithFormat:@"%@真正在上传%@",self.host,self.fileName];
//把剩余文件的数据取出来,放到可变data里
NSData *subFileData = [data subdataWithRange:NSMakeRange(100, data.length-100)];
self.allData = [NSMutableData data];
[self.allData appendData:subFileData];
//每次向服务器放数据的时候 都要将进度条的值改变。
self.myPV.progress = self.allData.length *1.0/self.fileLength;
if (self.allData.length == self.fileLength) {//这么判断表示已经传完了
NSString *toPath = [NSString stringWithFormat:@"/Documents/%@",self.fileName];
[self.allData writeToFile:toPath atomically:YES];
//在传完的时候 告诉lable,谁谁谁 上传 什么文件完成
self.statusLable.text = [NSString stringWithFormat:@"%@上传%@完成",self.host,self.fileName];
}
}
else if([type isEqualToString:@"getFileList"]){
}
else//下载
{
}
}else{//接收到的文件数据
[self.allData appendData:data];
//每次向服务器放数据的时候 都要将进度条的值改变。
self.myPV.progress = self.allData.length *1.0/self.fileLength;
if (self.allData.length == self.fileLength) {//这么判断表示已经传完了
NSString *toPath = [NSString stringWithFormat:@"//Users/gj/Desktop/保存文件/%@",self.fileName];
[self.allData writeToFile:toPath atomically:YES];
self.statusLable.text = [NSString stringWithFormat:@"%@上传%@完成!!!",self.host,self.fileName];
}
}
[sock readDataWithTimeout:-1 tag:0];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
以上上传功能实现了,现在就剩余下载功能了; 实现服务器的文件列表了;
下载功能的代码实现:
需要获取,文件夹下面的数据, 然后客户端才可以下载。
实现这些东西,需要一个文件类, 客户端不断的接受数据 。
把对象转换成data类型 需要的代码与实现方法:
NSData *fileData = [NSKeyedArchiver archivedDataWithRootObject:files];
@interface File : NSObject<NSCoding>
@property (nonatomic,copy)NSString *name;
@property (nonatomic)int length;
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInt:self.length forKey:@"length"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.length = [aDecoder decodeIntForKey:@"length"];
}
return self;
}
#import "ServerFilesTableViewController.h"
#import "AsyncSocket.h"
#import "Utils.h"
#import "File.h"
@interface ServerFilesTableViewController ()<AsyncSocketDelegate>
@property (nonatomic,strong)AsyncSocket *clientSocket;
@property (nonatomic,strong)NSArray *files;
@end
@implementationServerFilesTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.clientSocket = [[AsyncSocket alloc]initWithDelegate:self];
[self.clientSocket connectToHost:@"192.168.1.12" onPort:8800 error:nil];
NSString *headerString = @"getFileList&&&&";
NSMutableData *data = [Utils getAllDataWithHeaderString:headerString];
[self.clientSocket writeData:data withTimeout:-1 tag:0];
[self.clientSocket readDataWithTimeout:-1 tag:0];
}
-(void)onSocket:(AsyncSocket *)sockdidReadData:(NSData *)data withTag:(long)tag{
// //得到了服务器列表返回的数据
self.files = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[self.tableView reloadData];//反归档将数据解出来;
//因为这个数据不是立即就得到的 对页面的数据源进行了修改,(只要不是进到界面立即处理的)
//只要是传过来的数据 有时差,就证明修改了数据源,就需要进行[self.tableView reloadData];
// [self.tableView reloadData];
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return self.files.count;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
File *file = self.files[indexPath.row];
cell.textLabel.text = file.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"%dB",file.length];
return cell;
}
@end