• 关于

    追加字段

    的搜索结果

回答

如上图所未,左边一个是按 {“country”: 1, “carsOwned”: 1} 的顺序建立的索引。而右边是按 {“carsOwned”: 1, ”country”: 1} 顺序建立的索引。如果我们执行上面的查询,通过左边的索引,我们需要将 country 值为A的(左图的左边一支)所有子节点以及country 值为G的(左图的右边一支)所有子节点都取也来。然后再对取出来的这些数据按 carsOwned 值进行一次排序操作。所以说上面 explain 输出了一个 “scanAndOrder” : true 的提示,就是说这次查询,是先进行了scan获取到数据,再进行了独立的排序操作的。那如果我们使用右边的索引来做查询,结果就不太一样了。我们没有将排序字段放在最后,而是放在了前面,相反把筛选字段放在了后面。那这样的结果就 是:我们会从值为1的节点开始遍历(右图的左边一支),当发现有 country 值为 A 或 G 的,就直接放到结果集中。当完成指定数量(指定 limit 个数)的查找后。我们就可以直接将结果返回了,因为这时候,所有的结果本身就是按 carsOwned 正序排列的。对于上面的数据集,如果我们需要2条结果。我们通过左图的索引需要扫描到4条记录,然后对4条记录进行排序才能返回结果。而右边只需要我们扫描2条结果就能直接返回了(因为查询的过程就是按需要的顺序去遍历索引的)。所以,在有范围查询(包括$in, $gt, $lt 等等)的时候,其实刻意在后面追加排序索引通常是没有效果的。因为在进行范围查询的过程中,我们得到的结果集本身并不是按追加的这个字段来排的,还需要进 行一次额外的排序才行。而在这种情况下,可能反序建立索引(排序字段在前、范围查询字段在后)反而会是一个比较优的选择。当然,是否更优也和具体的数据集有关。

落地花开啦 2019-12-02 01:49:26 0 浏览量 回答数 0

回答

你不能再追加一个字段用来存储长度么?如果是16进制数据而不是字符串,又是使用的定长的方式存储,显然不能将metadata和data混在一起。

a123456678 2019-12-02 03:11:50 0 浏览量 回答数 0

回答

你不能再追加一个字段用来存储长度么?如果是16进制数据而不是字符串,又是使用的定长的方式存储,显然不能将metadata和data混在一起。

a123456678 2019-12-02 03:11:50 0 浏览量 回答数 0

问题

如何打开空的SQL窗口和SQL窗口

云栖大讲堂 2019-12-01 21:29:01 1352 浏览量 回答数 0

问题

请教两个问题 1.Postgresql bytea 字段保存byte数组,在不断的追加更新后,表膨胀的非常厉害,这个问题有什么好的解决办法么,服务器环境(windows server2008) 2. 时序数据,在磁盘随机读能力比较低的情况下,单机,3000个测量点,每个测量点30种指标,每5秒产生一个数据,1天约几千万(之前每天几亿,稀释后减少到几千万),按测量点、指标类型、时间区间查询 使用TimeScale也测试过,分区表都试验过,Brin 索引和Btree索引都测试过,拉到内存的数据查询速

我叫石头 2019-12-01 19:32:31 743 浏览量 回答数 1

回答

1. 原始单据与实体之间的关系 可以是一对一、一对多、多对多的关系。在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体。在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体。 这里的实体可以理解为基本表。明确这种对应关系后,对我们设计录入界面大有好处。 〖例1〗:一份员工履历资料,在人力资源信息系统中,就对应三个基本表:员工基本情况表、社会关系表、工作简历表。这就是“一张原始单证对应多个实体”的典型例子。 2. 主键与外键 一般而言,一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体, 可以定义主键,也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。 主键与外键的设计,在全局数据库的设计中,占有重要地位。当全局数据库的设计完成以后,有个美国数据库设计专家说:“键,到处都是键,除了键之外,什么也没有”,这就是他的数据库设计经验之谈,也反映了他对信息系统核心(数据模型)的高度抽象思想。 因为:主键是实体的高度抽象,主键与外键的配对,表示实体之间的连接。 3. 基本表的性质 基本表与中间表、临时表不同,因为它具有如下四个特性: 原子性。基本表中的字段是不可再分解的。原始性。基本表中的记录是原始数据(基础数据)的记录。演绎性。由基本表与代码表中的数据,可以派生出所有的输出数据。稳定性。基本表的结构是相对稳定的,表中的记录是要长期保存的。理解基本表的性质后,在设计数据库时,就能将基本表与中间表、临时表区分开来。 4. 范式标准 基本表及其字段之间的关系, 应尽量满足第三范式。但是,满足第三范式的数据库设计,往往不是最好的设计。为了提高数据库的运行效率,常常需要降低范式标准:适当增加冗余,达到以空间换时间的目的。〖例2〗:有一张存放商品的基本表,如表1所示。“金额”这个字段的存在,表明该表的设计不满足第三范式,因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。在Rose 2002中,规定列有两种类型:数据列和计算列。“金额”这样的列被称为“计算列”,而“单价”和“数量”这样的列被称为“数据列”。640?wx_fmt=png 表1 商品表的表结构 5. 通俗地理解三个范式 通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解): 第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解 第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性; 第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。 没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余。 6. 要善于识别与正确处理多对多的关系 若两个实体之间存在多对多的关系,则应消除这种关系。消除的办法是,在两者之间增加第三个实体。这样,原来一个多对多的关系,现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。 这里的第三个实体,实质上是一个较复杂的关系,它对应一张基本表。一般来讲,数据库设计工具不能识别多对多的关系,但能处理多对多的关系。 〖例3〗:在“图书馆信息系统”中,“图书”是一个实体,“读者”也是一个实体。这两个实体之间的关系,是一个典型的多对多关系:一本图书在不同时间可以被多个读者借阅,一个读者又可以借多本图书。为此,要在二者之间增加第三个实体,该实体取名为“借还书”,它的属性为:借还时间、借还标志(0表示借书,1表示还书),另外,它还应该有两个外键(“图书”的主键,“读者”的主键),使它能与“图书”和“读者”连接。 7. 主键PK的取值方法 PK是供程序员使用的表间连接工具,可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时,建议字段的个数不要太多,多了不但索引占用空间大,而且速度也慢。 8. 正确认识数据冗余 主键与外键在多表中的重复出现, 不属于数据冗余,这个概念必须清楚,事实上有许多人还不清楚。非键字段的重复出现, 才是数据冗余!而且是一种低级冗余,即重复性的冗余。高级冗余不是字段的重复出现,而是字段的派生出现。〖例4〗:商品中的“单价、数量、金额”三个字段,“金额”就是由“单价”乘以“数量”派生出来的,它就是冗余,而且是一种高级冗余。冗余的目的是为了提高处理速度。 只有低级冗余才会增加数据的不一致性,因为同一数据,可能从不同时间、地点、角色上多次录入。因此,我们提倡高级冗余(派生性冗余),反对低级冗余(重复性冗余)。 9. E--R图没有标准答案 信息系统的E--R图没有标准答案,因为它的设计与画法不是惟一的,只要它覆盖了系统需求的业务范围和功能内容,就是可行的。反之要修改E--R图。尽管它没有惟一的标准答案,并不意味着可以随意设计。好的E—R图的标准是:结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。 10. 视图技术在数据库设计中很有用 与基本表、代码表、中间表不同,视图是一种虚表,它依赖数据源的实表而存在。视图是供程序员使用数据库的一个窗口,是基表数据综合的一种形式, 是数据处理的一种方法,是用户数据保密的一种手段。 为了进行复杂处理、提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。若三层视图仍不够用, 则应在视图上定义临时表, 在临时表上再定义视图。这样反复交迭定义, 视图的深度就不受限制了。 对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统,视图的作用更加重要。这些系统的基本表完成物理设计之后,立即在基本表上建立第一层视图,这层视图的个数和结构,与基本表的个数和结构是完全相同。并且规定,所有的程序员,一律只准在视图上操作。 只有数据库管理员,带着多个人员共同掌握的“安全钥匙”,才能直接在基本表上操作。请读者想想:这是为什么? 11. 中间表、报表和临时表 中间表是存放统计数据的表,它是为数据仓库、输出报表或查询结果而设计的,有时它没有主键与外键(数据仓库除外)。临时表是程序员个人设计的,存放临时记录,为个人所用。基表和中间表由DBA维护,临时表由程序员自己用程序自动维护。 12. 完整性约束表现在三个方面 域的完整性:用Check来实现约束,在数据库设计工具中,对字段的取值范围进行定义时,有一个Check按钮,通过它定义字段的值城。 参照完整性:用PK、FK、表级触发器来实现。用户定义完整性:它是一些业务规则,用存储过程和触发器来实现。 13. 防止数据库设计打补丁的方法是“三少原则” 1、一个数据库中表的个数越少越好。只有表的个数少了,才能说明系统的E--R图少而精,去掉了重复的多余的实体,形成了对客观世界的高度抽象,进行了系统的数据集成,防止了打补丁式的设计; 2、一个表中组合主键的字段个数越少越好。因为主键的作用,一是建主键索引,二是做为子表的外键,所以组合主键的字段个数少了,不仅节省了运行时间,而且节省了索引存储空间; 3、一个表中的字段个数越少越好。只有字段的个数少了,才能说明在系统中不存在数据重复,且很少有数据冗余,更重要的是督促读者学会“列变行”,这样就防止了将子表中的字段拉入到主表中去,在主表中留下许多空余的字段。所谓“列变行”,就是将主表中的一部分内容拉出去,另外单独建一个子表。这个方法很简单,有的人就是不习惯、不采纳、不执行。 数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点。“三少”是一个整体概念,综合观点,不能孤立某一个原则。该原则是相对的,不是绝对的。“三多”原则肯定是错误的。试想:若覆盖系统同样的功能,一百个实体(共一千个属性) 的E--R图,肯定比二百个实体(共二千个属性)的E--R图,要好得多。 提倡“三少”原则,是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将文件系统集成为应用数据库,将应用数据库集成为主题数据库,将主题数据库集成为全局综合数据库。 集成的程度越高,数据共享性就越强,信息孤岛现象就越少,整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。提倡“三少”原则的目的,是防止读者利用打补丁技术,不断地对数据库进行增删改,使企业数据库变成了随意设计数据库表的“垃圾堆”,或数据库表的“大杂院”,最后造成数据库中的基本表、代码表、中间表、临时表杂乱无章,不计其数,导致企事业单位的信息系统无法维护而瘫痪。 “三多”原则任何人都可以做到,该原则是“打补丁方法”设计数据库的歪理学说。“三少”原则是少而精的原则,它要求有较高的数据库设计技巧与艺术,不是任何人都能做到的,因为该原则是杜绝用“打补丁方法”设计数据库的理论依据。 14. 提高数据库运行效率的办法 在给定的系统硬件和系统软件条件下,提高数据库系统的运行效率的办法是:在数据库物理设计时,降低范式,增加冗余, 少用触发器, 多用存储过程。 当计算非常复杂、而且记录条数非常巨大时(例如一千万条),复杂计算要先在数据库外面,以文件系统方式用C++语言计算处理完成之后,最后才入库追加到表中去。这是电信计费系统设计的经验。 发现某个表的记录太多,例如超过一千万条,则要对该表进行水平分割。水平分割的做法是,以该表主键PK的某个值为界线,将该表的记录水平分割为两个表。若发现某个表的字段太多,例如超过八十个,则垂直分割该表,将原来的一个表分解为两个表。 对数据库管理系统DBMS进行系统优化,即优化各种系统参数,如缓冲区个数。在使用面向数据的SQL语言进行程序设计时,尽量采取优化算法。 总之,要提高数据库的运行效率,必须从数据库系统级优化、数据库设计级优化、程序实现级优化,这三个层次上同时下功夫。

茶什i 2019-12-27 15:54:46 0 浏览量 回答数 0

回答

你这个需求我之前恰好做过类似的先要有个表存权限有关的数据 并在用户登陆后缓存起来然后所有的查询默认把当前登陆用户的权限数据放到查询里去(可以配置不带权限 该功能是一个隐式的操作 类似Filter)这里就会出现你说的这个问题 如果不对产生的SQL进行解析,那么很有可能被别名干扰 而且达不到最大效率 然后还有个问题是列对应的问题 也就是哪些列匹配哪些列 这个也需要定义我后来的处理方式是 1.争取所有表的字段进行统一 尽量避免同一个属性 多个命名的情况 如果出现则需要显示配置一下2.拿到所有需要过滤的表与列的信息(多种设置 默认不启用 一般配置为先全开 再去关掉不需要的)3.对查询SQL进行解析 这里有个重点 不允许内嵌SQL的列用别名 但是允许表别名(不然解析器写起来就麻烦了 为了达到效率最高化 最好是预处理我用的是MyBatis) 然后在表后面追加查询 默认放最里面

爵霸 2019-12-02 01:56:49 0 浏览量 回答数 0

问题

Angular6使用get请求后端数据,报错跨源!!?报错

爱吃鱼的程序员 2020-06-06 15:21:54 0 浏览量 回答数 1

回答

自己解决了。用sqlldr先写一个insert.ctl文件 load data infile '20141010_1_3gpostuser_759.txt' append into table BI_3G_POSTPAYUSER_T fields terminated by '|' #字段分割符 ( row1, row2 , …… ) 注:因为我这个数据是追加,所以用append,如果纯插入空表,可以用insert。 除此外还有其他几种方式 REPLACE // 原先的表有数据 原先的数据会全部删除 TRUNCATE // 指定的内容和replace的相同 会用truncate语句删除现存数据。 再写个insert.sh,用来执行。因为我这要导三个文件,用了个循环。 #!/bin/sh #最好把环境变量也引入下 filelist=$(ls) for file in $filelist do sed -i "s/20.*_3gpostuser_7.*\.txt/${file}/g" /home/interface/insert.ctl sqlldr user/pass@sid control=/home/interface/insert.ctl #控制器路径 mv $file ../bak/$file'.bak' done

a123456678 2019-12-02 02:54:45 0 浏览量 回答数 0

问题

iOS-SDK之如何实现上传文件(一)?

青衫无名 2019-12-01 21:41:52 1100 浏览量 回答数 0

回答

回 楼主(百炼钢) 的帖子 你指的是oss上传中的callback功能把?可以参考这个文档里对callback的说明使用其中在Header中携带参数的方式来实现,js sdk 接口中option参数可以包含header字段。以下是可以参考的oss callback功能说明和js sdk 参数的说明: https://help.aliyun.com/document_detail/31989.html?spm=5176.doc31961.6.874.ktSWhX https://github.com/ali-sdk/ali-oss#putname-file-options ------------------------- 回 4楼(百炼钢) 的帖子 根据callback文档里的说明,使用js sdk接口的option参数,这个参数可以追加header字段,就是之前发的那个github的地址里有说明这个字段,以下sample代码方便你理解(注:sample代码没有经过严格测试仅用来参考),其中your_var_1和your_var_2应该就是你需要的参数字段,如下: var co = require('co'); var OSS = require('ali-oss'); var urlutil = require('url'); var client = new OSS({   region: 'xxxx',   accessKeyId: 'xxxx',   accessKeySecret: 'xxxx' }); encodeCallback = function (cb) {   var url = urlutil.parse(cb.url);   url.query = cb.query;   var json = {     callbackUrl: url.format(),     callbackBody: cb.body,     callbackBodyType: cb.contentType || 'application/x-www-form-urlencoded'   };   return new Buffer(JSON.stringify(json)).toString('base64'); }; co(function* () {   client.useBucket('your_bucket');   var result = yield client.put('object_name', 'local_file_path',                                 {headers: {                                     'x-oss-callback': encodeCallback({                                         url: 'http://call_back_url:xxx/xxx',                                         query: {your_var_1: 'your_var_value_1', your_var_2: 'your_var_value_2'},                                         body: 'bucket=${bucket}&object=${object}'                                 })                                     }                                 });   console.log(result); }).catch(function (err) {   console.log(err); });

mars.liu 2019-12-01 23:40:46 0 浏览量 回答数 0

问题

版本历史

反向一觉 2019-12-01 21:02:56 1049 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:08 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:07 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:07 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:07 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:09 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:08 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:08 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:07 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:06 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,分片上传和断点续传。 简单上传上传Object可以直接上传OSSData,或者通过NSURL上传一个文件: OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 可选字段,可不设置put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject// put.contentType = @"";// put.contentMd5 = @"";// put.contentEncoding = @"";// put.contentDisposition = @"";// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 上传到文件目录OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。 如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。 上传时设置Content-Type和开启校验MD5上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。 OSSPutObjectRequest * put = [OSSPutObjectRequest new];// 必填字段put.bucketName = @"<bucketName>";put.objectKey = @"<objectKey>";put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// put.uploadingData = <NSData *>; // 直接上传NSData// 设置Content-Type,可选put.contentType = @"application/octet-stream";// 设置MD5校验,可选put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据// 进度设置,可选put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度 NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * putTask = [client putObject:put];[putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); } else { NSLog(@"upload object failed, error: %@" , task.error); } return nil;}];// [putTask waitUntilFinished];// [put cancel]; 追加上传Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。 OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];// 必填字段append.bucketName = @"<bucketName>";append.objectKey = @"<objectKey>";append.appendPosition = 0; // 指定从何处进行追加NSString * docDir = [self getDocumentDirectory];append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];// 可选字段append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject// append.contentType = @"";// append.contentMd5 = @"";// append.contentEncoding = @"";// append.contentDisposition = @"";OSSTask * appendTask = [client appendObject:append];[appendTask continueWithBlock:^id(OSSTask *task) { NSLog(@"objectKey: %@", append.objectKey); if (!task.error) { NSLog(@"append object success!"); OSSAppendObjectResult * result = task.result; NSString * etag = result.eTag; long nextPosition = result.xOssNextAppendPosition; } else { NSLog(@"append object failed, error: %@" , task.error); } return nil;}]; 上传后回调通知客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。 具体说明参考:Callback 代码示例: OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = @"<bucketName>";request.objectKey = @"<objectKey>";request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];// 设置回调参数request.callbackParam = @{ @"callbackUrl": @"<your server callback address>", @"callbackBody": @"<your callback body>" };// 设置自定义变量request.callbackVar = @{ @"<var1>": @"<value1>", @"<var2>": @"<value2>" };request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};OSSTask * task = [client putObject:request];[task continueWithBlock:^id(OSSTask *task) { if (task.error) { OSSLogError(@"%@", task.error); } else { OSSPutObjectResult * result = task.result; NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@", result.requestId, result.httpResponseHeaderFields, result.serverReturnJsonString); } return nil;}]; 分片上传因为篇幅的原因,分片上传参考:分片上传 断点续传 特别注意: 断点续传暂时只支持上传本地文件。 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。** 在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。 在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,如果用户设置取消时不删除断点记录。再次上传将从断点记录处继续上传。详见随后的范例。 断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理。 出于碎片管理的原因,如果在断点续传时取消当前任务。默认会同步清理已经上传到服务器的分片。如果取消时需要保留断点上传记录,需要指定断点记录的保存文件夹并修改deleteUploadIdOnCancelling参数。需要注意,如果本地保留记录时间过长,且Bucket设置lifeCycle规则定时清理了服务端分片。会出现服务端和移动端记录不一致的问题。 说明: 断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。 在本地持久保存断点记录的调用方式(默认是不设置): OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = OSS_BUCKET_PRIVATE;//...NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];resumableUpload.recordDirectoryPath = cachesDir; 断点续传功能实现 // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];resumableUpload.bucketName = <bucketName>;resumableUpload.objectKey = <objectKey>;resumableUpload.partSize = 1024 * 1024;resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);};NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];//设置断点记录文件resumableUpload.recordDirectoryPath = cachesDir;//设置NO,取消时,不删除断点记录文件,如果不进行设置,默认YES,是会删除断点记录文件,下次再进行上传时会重新上传。resumableUpload.deleteUploadIdOnCancelling = NO;resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];OSSTask * resumeTask = [client resumableUpload:resumableUpload];[resumeTask continueWithBlock:^id(OSSTask *task) { if (task.error) { NSLog(@"error: %@", task.error); if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) { // 该任务无法续传,需要获取新的uploadId重新上传 } } else { NSLog(@"Upload file success"); } return nil;}];// [resumeTask waitUntilFinished];// [resumableUpload cancel]; 数据完整性校验因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。 MD5校验 需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。 OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = BUCKET_NAME;...request.contentMd5 = [OSSUtil fileMD5String:filepath]; CRC校验 与MD5相比,CRC64可以同时上传并计算CRC值。 // 构造上传请求OSSPutObjectRequest * request = [OSSPutObjectRequest new];request.bucketName = OSS_BUCKET_PRIVATE;///....request.crcFlag = OSSRequestCRCOpen;// 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。OSSTask * task = [_client putObject:request];[[task continueWithBlock:^id(OSSTask *task) { //如果crc效验失败,会有error XCTAssertNil(task.error); return nil;}] waitUntilFinished];

2019-12-01 23:14:08 0 浏览量 回答数 0

回答

发生的场景:服务器端接收客户端请求的时候,一般需要进行签名验证,客户端IP限定等情况,在进行客户端IP限定的时候,需要首先获取该真实的IP。 一般分为两种情况:   方式一、客户端未经过代理,直接访问服务器端(nginx,squid,haproxy);   方式二、客户端通过多级代理,最终到达服务器端(nginx,squid,haproxy); 客户端请求信息都包含在HttpServletRequest中,可以通过方法getRemoteAddr()获得该客户端IP。   方式一形式,可以直接获得该客户端真实IP。   方式二中通过代理的形式,此时经过多级反向的代理,通过方法getRemoteAddr()得不到客户端真实IP,可以通过x-forwarded-for获得转发后请求信息。当客户端请求被转发,IP将会追加在其后并以逗号隔开,例如:10.47.103.13,4.2.2.2,10.96.112.230。 请求中的参数:   request.getHeader("x-forwarded-for") : 10.47.103.13,4.2.2.2,10.96.112.230   request.getHeader("X-Real-IP") : 10.47.103.13   request.getRemoteAddr():10.96.112.230 客户端访问经过转发,IP将会追加在其后并以逗号隔开。最终准确的客户端信息为: x-forwarded-for 不为空,则为逗号前第一个IP ; X-Real-IP不为空,则为该IP ; 否则为getRemoteAddr() ; 相关请求头的解释: X-Forwarded-For :这是一个 Squid 开发的字段,只有在通过了HTTP代理或者负载均衡服务器时才会添加该项。         格式为X-Forwarded-For:client1,proxy1,proxy2,一般情况下,第一个ip为客户端真实ip,后面的为经过的代理服务器ip。现在大部分的代理都会加上这个请求头。 Proxy-Client-IP/WL- Proxy-Client-IP :这个一般是经过apache http服务器的请求才会有,用apache http做代理时一般会加上Proxy-Client-IP请求头,而WL-Proxy-Client-IP是他的weblogic插件加上的头。 HTTP_CLIENT_IP :有些代理服务器会加上此请求头。 X-Real-IP :nginx代理一般会加上此请求头。

景凌凯 2020-03-30 09:46:17 0 浏览量 回答数 0

问题

将数组追加到FormData并通过AJAX发送

保持可爱mmm 2020-02-08 11:57:16 0 浏览量 回答数 1

问题

MaxCompute用户指南:数据上传下载:通过数据集成导入/导出

行者武松 2019-12-01 22:01:54 1749 浏览量 回答数 0

问题

Apache Flink常见问题汇总【精品问答】

黄一刀 2020-05-19 17:51:47 11230 浏览量 回答数 2

问题

Data Pipeline数据如何导入?

nicenelly 2019-12-01 21:25:32 1171 浏览量 回答数 0

问题

Data Pipeline数据如何导入?

nicenelly 2019-12-01 21:10:55 1411 浏览量 回答数 0

回答

通过上述部署与配置,多个Web应用已经可以共用一个登录服务。但是,上述过程中作为CAS Client端的Web应用只取得了用户登录名称信息,而在实际应用中,Web应用往往需要获得登录用户更多的信息,例如会员等级、性别、住址等。要达到此目的,只需对Server端稍做修改即可实现。 1. 服务端配置及修改 假定上述存储用户信息的数据表userinfo中还包含一个名为address的用于存储用户地址的字段,而Web应用程序希望能够从CAS Server处获得当前登录用户的地址信息,则Server端需要按以下内容修改deployerConfigContext.xml。部分配置说明请参见注释。 <!--将原有attributeRepository配置注释 --> <!-- <beanid="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"> <propertyname="backingMap"> <map> <entrykey="uid" value="uid" /> <entrykey="eduPersonAffiliation" value="eduPersonAffiliation"/> <entrykey="groupMembership" value="groupMembership" /> </map> </property> </bean> --> <!--新增attributeRepository配置(开始) --> <bean class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"id="attributeRepository"> <!-- 指定使用的数据源,此处dataSource是已配置好的数据源 --> <constructor-arg index="0"ref="dataSource"/> <!-- 从数据库中查询信息的SQL语句,通常只需要修改表名即可 --> <constructor-arg index="1" value="select * fromuserinfo where {0}"/> <propertyname="queryAttributeMapping"> <map> <!-- 上述查询的参数,将userName替换为表中表示用户名的字段名称 --> <entrykey="username" value="userName"/> </map> </property> <propertyname="resultAttributeMapping"> <map> <!-- 需要返回给Web应用的其它信息,多个信息时可继续增加entry节点--> <!--key值为数据表中的字段名称,value值为Client端取值时的名称标识--> <entry key="address" value="address"/> </map> </property> </bean> <!--新增attributeRepository配置(结束) --> <bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"> <propertyname="registeredServices"> <list> <beanclass="org.jasig.cas.services.RegexRegisteredService"> <propertyname="id" value="0" /> <propertyname="name" value="HTTP and IMAP" /> <propertyname="description" value="Allows HTTP(S) and IMAP(S)protocols" /> <propertyname="serviceId" value="^(https?|imaps?)://.*" /> <propertyname="evaluationOrder" value="10000001" /> <!--增加此项配置 --> <property name="ignoreAttributes" value="true"/> </bean> … … </list> </property> </bean> CASServer要将额外的信息传递至Client端,还需要修改完成信息组装的文件WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp。casServiceValidationSuccess.jsp负责组装包含用户信息的XML,因此修改部分是将需要传递的额外信息加入到它最终生成的XML文件之中。具体修改如下: <cas:serviceResponsexmlns:cas=' http://www.yale.edu/tp/cas'> <cas:authenticationSuccess> <cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user> <!-- 新增额外信息(开始) --> <c:iftest="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes)> 0}"> <cas:attributes> <c:forEachvar="attr"items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}"> <!--注意此行的正确写法,网上资料基本都是错误的--> <cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}> </c:forEach> </cas:attributes> </c:if> <!-- 新增额外信息(结束) --> <c:if test="${not emptypgtIou}"> <cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket> </c:if> <c:if test="${fn:length(assertion.chainedAuthentications)> 1}"> <cas:proxies> <c:forEachvar="proxy" items="${assertion.chainedAuthentications}"varStatus="loopStatus" begin="0"end="${fn:length(assertion.chainedAuthentications)-2}"step="1"> <cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy> </c:forEach> </cas:proxies> </c:if> </cas:authenticationSuccess> </cas:serviceResponse> 2. Java Client端取得更多用户信息 Java Client端不需要做任何修改就可以继续正常使用CAS服务,如果需要取得用户更多信息,可以通过AttributePrincipal对象取得Attribute列表(一个Map对象)后进行查询。 修改前述Java Client的示例代码,在最后追加取得address信息的代码,重启服务并重新访问页面,可以看到页面上显示了当前用户的address信息。 <%@pageimport="org.jasig.cas.client.authentication.AttributePrincipal" %> <%@pageimport="org.jasig.cas.client.validation.Assertion" %> <%@page import="java.util.*" %> <% String loginName1 = request.getRemoteUser(); %> request.getRemoteUser(): <%=loginName1%><br/> <% AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal(); String loginName2 = principal.getName(); %> request.getUserPrincipal().getName():<%=loginName2%><br/> <% Object object =request.getSession().getAttribute("_const_cas_assertion_"); Assertion assertion =(Assertion)object; String loginName3 =assertion.getPrincipal().getName(); %> request.getSession().getAttribute("_const_cas_assertion_").getPrincipal().getName():<%=loginName3%><br/> “答案来源于网络,供您参考” 希望以上信息可以帮到您!

牧明 2019-12-02 02:17:26 0 浏览量 回答数 0

问题

MaxCompute用户指南:SQL:INSERT操作

行者武松 2019-12-01 22:02:56 1797 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 企业建站模板