资讯专栏INFORMATION COLUMN

为七牛iOS SDK添加ALAsset上传支持

ztyzz / 2567人阅读

摘要:本除部分译文外,所有内容均为原创,如有雷同,算我抄你七牛官方已经加入了对的支持。解决方案为便于说明,假定有实例。首先为添加在方法里会为此属性赋值。

本blog除部分译文外,所有内容均为原创,如有雷同,算我抄你:-)

Update:七牛官方SDK已经加入了对ALAsset的支持。 问题描述

七牛iOS SDK的上传API只有两个

objc@interface QNUploadManager : NSObject

- (void)putData:(NSData *)data
            key:(NSString *)key
          token:(NSString *)token
       complete:(QNUpCompletionHandler)completionHandler
         option:(QNUploadOption *)option;

- (void)putFile:(NSString *)filePath
            key:(NSString *)key
          token:(NSString *)token
       complete:(QNUpCompletionHandler)completionHandler
         option:(QNUploadOption *)option;

@end

其中putFileXXX是针对文件上传的,这个方法内部是依赖NSFileManager来获取文件信息的

objcNSError *error = nil;
NSDictionary *fileAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error];

NSNumber *fileSizeNumber = fileAttr[NSFileSize];
UInt32 fileSize = [fileSizeNumber intValue];
NSData *data = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];

那么问题来了,对于ALAsset,即系统相册中的图片或视频,获取到的assetURL是类似于如下形式的:

shassets-library://asset/asset.MOV?id=A16D4A3B-664E-4A75-90E8-37EA3F04FF2E&ext=MOV

NSFileManager无法处理,因而无法正确获取文件大小等信息,更不用说上传了。

解决方案

为便于说明,假定有ALAsset实例asset。
首先,通过asset.defaultRepresentation.size能够获取到对应文件的大小。为QNUploadManager创建一个category,如下

objc@interface QNUploadManager (ALAssetSupport)

- (void)putALasset:(ALAsset *)asset
               key:(NSString *)key
             token:(NSString *)token
          complete:(QNUpCompletionHandler)completionHandler
            option:(QNUploadOption *)option;


@end

具体实现如下

objc- (void)putALasset:(ALAsset *)asset
               key:(NSString *)key
             token:(NSString *)token
          complete:(QNUpCompletionHandler)completionHandler
            option:(QNUploadOption *)option
{
    //other code...


        QNResumeUpload *up = [[QNResumeUpload alloc]
                              initWithData:nil
                              withSize:(UInt32)asset.defaultRepresentation.size
                              withKey:key
                              withToken:token
                              withCompletionHandler:complete
                              withOption:option
                              withModifyTime:modifyTime
                              withRecorder:recorder
                              withRecorderKey:recorderKey
                              withHttpManager:[self getHttpManagerProperty]];
        up.asset = asset;
    }
}

从上面的代码可以看到,QNUploadManager实际上只是获取文件信息,做一些预处理,而真正的上传过程是由QNResumeUpload完成的。QNResumeUpload的初始化入参很多,需要注意的是data和size,一个简化版的initXXX如下

objc- (instancetype)initWithData:(NSData *)data
                    withSize:(UInt32)size
                     withOtherParameters:(XXX *)XXX;

其中data是文件句柄打开后的二进制数据,size是数据长度。
你一定已经发现我在putALassetXXX里很弱智地在data这个入参上传入了nil,这是有原因的。
打开QNResumeUpload.m,搜索data后发现,data本身只在2个获取分块数据的方法里涉及到

objc- (void)makeBlock:(NSString *)uphost
           offset:(UInt32)offset
        blockSize:(UInt32)blockSize
        chunkSize:(UInt32)chunkSize
         progress:(QNInternalProgressBlock)progressBlock
         complete:(QNCompleteBlock)complete;

- (void)putChunk:(NSString *)uphost
          offset:(UInt32)offset
            size:(UInt32)size
         context:(NSString *)context
        progress:(QNInternalProgressBlock)progressBlock
        complete:(QNCompleteBlock)complete; 
}

只要override它们,让它们支持ALAsset即可。
首先为QNResumeUpload添加property

objc@class ALAsset;

@interface QNResumeUpload (ALAssetSupport)
@property (nonatomic, strong) ALAsset *asset;

@end

在putALasset方法里会为此属性赋值。
接着写一个获取指定offset和length的data的方法

objc- (NSData *)dataFromALAssetAtOffset:(NSInteger)offset size:(NSInteger)size
{
    ALAssetRepresentation *rep = [self.asset defaultRepresentation];
    Byte *buffer = (Byte *)malloc(size);
    NSUInteger buffered = [rep getBytes:buffer fromOffset:offset length:size error:nil];

    return [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
}

最后在makeBlock和putChunk里调用此方法即可,以makeBlock为例

objc- (void)makeBlock:(NSString *)uphost
           offset:(UInt32)offset
        blockSize:(UInt32)blockSize
        chunkSize:(UInt32)chunkSize
         progress:(QNInternalProgressBlock)progressBlock
         complete:(QNCompleteBlock)complete
{
    NSData *data = [self dataFromALAssetAtOffset:offset size:chunkSize];//[self.data subdataWithRange:NSMakeRange(offset, (unsigned int)chunkSize)];
    NSString *url = [[NSString alloc] initWithFormat:@"http://%@/mkblk/%u", uphost, (unsigned int)blockSize];

    UInt32 crc = [QNCrc32 data:data];
    [self setChunkCrcValue:crc];

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
    SEL selector = @selector(post:withData:withCompleteBlock:withProgressBlock:);
#pragma clang diagnostic pop
    void (*typed_msgSend)(id, SEL, NSString *, NSData *, QNCompleteBlock, QNInternalProgressBlock) = (void *)objc_msgSend;
    typed_msgSend(self, selector, url, data, complete, progressBlock);
}
代码

https://github.com/NSFish/QiNiuALAssetSupport

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/15571.html

相关文章

  • 七牛云存储---JavaScript SDK 简单上传,走过的几个坑

    摘要:和七牛账号里面提供。自己设定的七牛云存储空间名,创建存储空间的时候注意地区应该默认是华东,不一样地区需要修改下里面指定的上传的域名,请去参考官方文档。若开启该选项,为自动生成上传成功后的文件名。 先放上几个用到的七牛官方网站: JavaScript SDK地址需要在页面中先引入 plupload 提供的 plupload.full.min.js(生产环境)然后再引入SDK里的 qini...

    or0fun 评论0 收藏0
  • 记录一下前端分片上传七牛云踩过的坑

    摘要:后来查阅了资料后自己手动实现了文件切片上传到服务器基本需求已经实现,但由于效率及稳定性问题后来决定还是直传文件到七牛云。总结起来七牛云上传的套路就是后台为你提供或者获取的接口地址之后上传的时候要带上这个。 起因 最近在工作中有个上传大文件的需求,原先咨询过组里的大佬给我推荐了百度的webupload,但后来引入之后发现它是基于jquery封装的。由于本身项目是基于vue开发的所以与j...

    ISherry 评论0 收藏0
  • 七牛云存储空间绑定自定义域名,并使用七牛云提供的免费SSL证书,将自定义加名升级为HTTPS

    摘要:现在我们必须给七牛云空间绑定一个自己的域名。如对七牛云及其他用户造成损害,七牛云保留进一步追责的权利。然而七牛目前并不支持这类短期的免费证书。 〇、七牛将定期回收测试域名,正在使用测试域名的小伙伴们必须设置自定义域名了 想必最近很多小伙伴都收到了这封来自七牛云的邮件,这意味着创建七牛云空间时附带自动生成的域名每30日就会变更一次,再也无法长期使用。现在我们必须给七牛云空间绑定一个自己的...

    yeooo 评论0 收藏0
  • 七牛云存储空间绑定自定义域名,并使用七牛云提供的免费SSL证书,将自定义加名升级为HTTPS

    摘要:现在我们必须给七牛云空间绑定一个自己的域名。如对七牛云及其他用户造成损害,七牛云保留进一步追责的权利。然而七牛目前并不支持这类短期的免费证书。 〇、七牛将定期回收测试域名,正在使用测试域名的小伙伴们必须设置自定义域名了 想必最近很多小伙伴都收到了这封来自七牛云的邮件,这意味着创建七牛云空间时附带自动生成的域名每30日就会变更一次,再也无法长期使用。现在我们必须给七牛云空间绑定一个自己的...

    yedf 评论0 收藏0
  • 用纯Javascript实现React Native的文件上传

    摘要:是上传到服务器的文件名,是请求令牌。七牛云将持续发布服务于企业的云服务,也会在第一时间发布平台的,让使用的小伙伴在第一时间集成七牛云的最新服务。 React Native 是最近两年最值得花时间跟进的移动开发技术,这个项目始于2013年Facebook内部的一个黑客马拉松项目,在2014年7月之前这个项目都偏向于实验性质,直到广告管理团队想要构建一个独立的iOS应用,然而这个团队并没有...

    JasonZhang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<