samba简介
Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源。通过设置“NetBIOS over TCP/IP”使得Samba不但能与局域网络主机分享资源,还能与全世界的电脑分享资源。
第三方库
1、如果当前osx系统没有编译过这些东西,会出现如图的错误,打开错误信息,然后到stackoverflower中找答案,在电脑上编译之后就不会出现这种错误了
2、KxSMBProvider 是一个用OC封装的库,里面有基本的增删改查的功能。如若需要其他功能,可以看libsmbclient文件研究
实现代码
#pragma mark - 文件上传(开始)
- (void)updateFileManagerWithArray:(NSMutableArray *)arr MomentType:(BOOL)type block:(KxSMBBlock)result{
//文件模型
for (LBFileManageModel *fileModel in arr) {
BOOL fileExist = NO;
for (int i = 0;i<self.files.count;i++) {
LBFileManageModel *existFileModel = self.files[i];
if([existFileModel.pathUrl isEqualToString:fileModel.pathUrl]){
fileExist = YES;
}
}
if(!fileExist){
[self.files addObject:fileModel];
NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(uploadLocalFiles:) object:fileModel];
operation.name = fileModel.pathUrl;
[self.fileUploadQueue addOperation:operation];
}
}
}
-(void)uploadLocalFiles:(LBFileManageModel *)fileModel{
self.fileManageModel = fileModel;
[self uploadVideo:fileModel];
}
-(void)uploadVideo:(LBFileManageModel *)video{
//改变
[self changeOperationIngStatusToUserDefault:@"selectFiles" andType:@"upload"];
//文件数据
ALAsset * asset = video.asset;
//根据asset获得分段数据
ALAssetRepresentation *representation = asset.defaultRepresentation;
//文件总大小
long long size = representation.size;
NSLog(@"上传文件总大小---%lld",size);
NSString *videoName = video.pathUrl;
//根据userDefaults里面该条数据存储的已经上传的长度来设置偏移量
NSArray *uploadData = [[NSUserDefaults standardUserDefaults] objectForKey:@"selectFiles"];
for (NSDictionary *dataDic in uploadData) {
NSString *dataName = dataDic[@"pathUrl"];
if([dataName isEqualToString:videoName]){
long long dataLength = [dataDic[@"dataLength"] longLongValue];
self.finishLength = dataLength;
//文件上传部分
long long otherLength = size - dataLength;
if(otherLength >= DATA_LENGTH){
[self getAssetData:asset andOffset:dataLength andLength:DATA_LENGTH];
}else{
[self getAssetData:asset andOffset:dataLength andLength:(int)otherLength];
}
}
}
NSString *path;
if(video.detailType == RequestMomentPhotoType){
path = [SMB_SERVER_PIC stringByAppendingSMBPathComponent:videoName];
}else{
path = [SMB_SERVER_VIDEO stringByAppendingSMBPathComponent:videoName];
}
KxSMBProvider *provider = [KxSMBProvider sharedSmbProvider];
dispatch_semaphore_t dsema = dispatch_semaphore_create(0);
[provider createFileAtPath:path overwrite:YES block:^(id result) {
if ([result isKindOfClass:[KxSMBItemFile class]]) {
self.itemFile = result;
[self uploadVideoData:self.buffer andAsset:asset andVideoName:videoName completionBlock:^{
dispatch_semaphore_signal(dsema);
}];
}else{
NSLog(@"创建路径失败");
dispatch_semaphore_signal(dsema);
}
}];
dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER);
}
#pragma mark - 分段获取文件data
-(NSData *)getAssetData:(ALAsset *)asset andOffset:(long long)offset andLength:(int)length{
NSData *fileData;
//根据asset获得分段数据
ALAssetRepresentation *representation = asset.defaultRepresentation;
//文件总大小
long long size = representation.size;
NSMutableData* data = [[NSMutableData alloc] initWithCapacity:length];
void* buffer = [data mutableBytes];
[representation getBytes:buffer fromOffset:offset length:length error:nil];
fileData = [[NSData alloc] initWithBytes:buffer length:length];
self.buffer = fileData;
return fileData;
}
//分段上传文件data (buffer里面的数据)
-(void)uploadVideoData:(NSData *)uploadData andAsset:(ALAsset *)asset andVideoName:(NSString *)videoName
completionBlock:(dispatch_block_t)completionBlock
{
//上传文件的名称
NSString *fileName = videoName;
__weak __typeof(self)wself = self;
//写操作的时候要注意要seek到指定位置
[self.itemFile seekToFileOffset:self.finishLength whence:SEEK_SET block:^(id _Nullable result) {
if([result isKindOfClass:[NSError class]]){
NSLog(@"seek失败---%@",result);
}else{
NSLog(@"seek成功---%@",result);
}
}];
//上传操作
[self.itemFile writeData:uploadData block:^(id result) {
NSData *dataResult = result;
if (![result isKindOfClass:[NSError class]]) {
long long bufferLength = (long long)self.buffer.length;
self.finishLength += bufferLength;
float progress = (float)self.finishLength / asset.defaultRepresentation.size;
NSLog(@"文件上传进度 -- %f",progress);
//更新进度
[self fileUploadProgress:progress andFile:fileName andData:self.finishLength andTotalData:asset.defaultRepresentation.size];
if(progress == 1.0){
[self deleteUploadFinishFiles:fileName];
}
int otherLength = (int)asset.defaultRepresentation.size - (int)self.finishLength;
NSData *bufferData = nil;
if((otherLength <= DATA_LENGTH) && (otherLength > 0)){
bufferData = [wself getAssetData:asset andOffset:self.finishLength andLength:otherLength];
}else if(otherLength > DATA_LENGTH){
bufferData = [wself getAssetData:asset andOffset:self.finishLength andLength:DATA_LENGTH];
}else{
NSLog(@"文件完整上传成功");
for (int i = 0; i<self.files.count; i++) {
LBFileManageModel *fileModel = self.files[i];
if([fileModel.pathUrl isEqualToString:fileName]){
[self.files removeObject:fileModel];
break;
}
}
self.finishLength = 0.0;
[self.itemFile close];
if (completionBlock) {
completionBlock();
}
//通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"uploadNotification" object:nil userInfo:nil];
if([self.delegate respondsToSelector:@selector(fileUploadFinish:)]){
[self.delegate fileUploadFinish:fileName];
}
[self deleteUploadFinishFiles:fileName];
return ;
}
if(bufferData){
//处理暂停逻辑
NSArray *updateFiles = [[NSUserDefaults standardUserDefaults] objectForKey:@"selectFiles"];
NSMutableArray *updateFilesMut = [NSMutableArray arrayWithArray:updateFiles];
BOOL uploadFileDefaultsExists = NO;
for (int i = 0; i < updateFilesMut.count; i++) {
NSDictionary *uploadFile = updateFilesMut[i];
NSMutableDictionary *dicFile = [NSMutableDictionary dictionaryWithDictionary:uploadFile];
if([dicFile[@"pathUrl"] isEqualToString:fileName]){
uploadFileDefaultsExists = YES;
if([dicFile[@"isSuspend"] integerValue]){
//已暂停
[self.itemFile close];
[self changeOperationIngStatusToUserDefaultSuspend:fileName andKey:@"selectFiles"];
if (completionBlock) {
completionBlock();
}
return;
}else{
//未暂停
[wself uploadVideoData:self.buffer andAsset:asset andVideoName:fileName completionBlock:completionBlock];
}
}
}
//数据被删除
if(!uploadFileDefaultsExists){
if (completionBlock) {
completionBlock();
}
for (int i = 0; i<self.files.count; i++) {
LBFileManageModel *fileModel = self.files[i];
if([fileModel.pathUrl isEqualToString:fileName]){
[self.files removeObject:fileModel];
break;
}
}
[self.itemFile close];
self.finishLength = 0.0;
return;
}
}
}
}];
}