全部产品
对象存储 OSS

上传文件

更新时间:2017-06-07 13:26:11   分享:   

简单上传

上传Object可以直接上传OSSData,或者通过NSURL上传一个文件:

  1. OSSPutObjectRequest * put = [OSSPutObjectRequest new];
  2. // 必填字段
  3. put.bucketName = @"<bucketName>";
  4. put.objectKey = @"<objectKey>";
  5. put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];
  6. // put.uploadingData = <NSData *>; // 直接上传NSData
  7. // 可选字段,可不设置
  8. put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
  9. // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度
  10. NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
  11. };
  12. // 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject
  13. // put.contentType = @"";
  14. // put.contentMd5 = @"";
  15. // put.contentEncoding = @"";
  16. // put.contentDisposition = @"";
  17. // put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部
  18. OSSTask * putTask = [client putObject:put];
  19. [putTask continueWithBlock:^id(OSSTask *task) {
  20. if (!task.error) {
  21. NSLog(@"upload object success!");
  22. } else {
  23. NSLog(@"upload object failed, error: %@" , task.error);
  24. }
  25. return nil;
  26. }];
  27. // [putTask waitUntilFinished];
  28. // [put cancel];

上传到文件目录

OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。

如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。

上传时设置Content-Type和开启校验MD5

上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。

  1. OSSPutObjectRequest * put = [OSSPutObjectRequest new];
  2. // 必填字段
  3. put.bucketName = @"<bucketName>";
  4. put.objectKey = @"<objectKey>";
  5. put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];
  6. // put.uploadingData = <NSData *>; // 直接上传NSData
  7. // 设置Content-Type,可选
  8. put.contentType = @"application/octet-stream";
  9. // 设置MD5校验,可选
  10. put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径
  11. // put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据
  12. // 进度设置,可选
  13. put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
  14. // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度
  15. NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
  16. };
  17. OSSTask * putTask = [client putObject:put];
  18. [putTask continueWithBlock:^id(OSSTask *task) {
  19. if (!task.error) {
  20. NSLog(@"upload object success!");
  21. } else {
  22. NSLog(@"upload object failed, error: %@" , task.error);
  23. }
  24. return nil;
  25. }];
  26. // [putTask waitUntilFinished];
  27. // [put cancel];

追加上传

Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。

  1. OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];
  2. // 必填字段
  3. append.bucketName = @"<bucketName>";
  4. append.objectKey = @"<objectKey>";
  5. append.appendPosition = 0; // 指定从何处进行追加
  6. NSString * docDir = [self getDocumentDirectory];
  7. append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];
  8. // 可选字段
  9. append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
  10. NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
  11. };
  12. // 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject
  13. // append.contentType = @"";
  14. // append.contentMd5 = @"";
  15. // append.contentEncoding = @"";
  16. // append.contentDisposition = @"";
  17. OSSTask * appendTask = [client appendObject:append];
  18. [appendTask continueWithBlock:^id(OSSTask *task) {
  19. NSLog(@"objectKey: %@", append.objectKey);
  20. if (!task.error) {
  21. NSLog(@"append object success!");
  22. OSSAppendObjectResult * result = task.result;
  23. NSString * etag = result.eTag;
  24. long nextPosition = result.xOssNextAppendPosition;
  25. } else {
  26. NSLog(@"append object failed, error: %@" , task.error);
  27. }
  28. return nil;
  29. }];

上传后回调通知

客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。

具体说明参考:Callback

代码示例:

  1. OSSPutObjectRequest * request = [OSSPutObjectRequest new];
  2. request.bucketName = @"<bucketName>";
  3. request.objectKey = @"<objectKey>";
  4. request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];
  5. // 设置回调参数
  6. request.callbackParam = @{
  7. @"callbackUrl": @"<your server callback address>",
  8. @"callbackBody": @"<your callback body>"
  9. };
  10. // 设置自定义变量
  11. request.callbackVar = @{
  12. @"<var1>": @"<value1>",
  13. @"<var2>": @"<value2>"
  14. };
  15. request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
  16. NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
  17. };
  18. OSSTask * task = [client putObject:request];
  19. [task continueWithBlock:^id(OSSTask *task) {
  20. if (task.error) {
  21. OSSLogError(@"%@", task.error);
  22. } else {
  23. OSSPutObjectResult * result = task.result;
  24. NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@",
  25. result.requestId,
  26. result.httpResponseHeaderFields,
  27. result.serverReturnJsonString);
  28. }
  29. return nil;
  30. }];

断点续传

在无线网络下,上传比较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,SDK提供了断点上传功能。

这个功能依赖OSS的分片上传接口实现,它不会在本地保存任何信息。在上传大文件前,您需要调用分片上传的初始化接口获得UploadId,然后持有这个UploadId调用断点上传接口,将文件上传。如果上传异常中断,那么,持有同一个UploadId,继续调用这个接口上传该文件,上传会自动从上次中断的地方继续进行。

如果上传已经成功,UploadId会失效,如果继续拿着这个UploadId上传文件,会遇到Domain为OSSClientErrorDomain,Code为OSSClientErrorCodeCannotResumeUpload的NSError,这时,需要重新获取新的UploadId上传文件。

也就是说,您需要自行保存和管理与您文件对应的UploadId。UploadId的获取方式参考后面的 分片上传 章节。

断点续传失败时,如果同一任务一直得不到续传,可能会在OSS上积累无用碎片。对这种情况,可以为Bucket设置lifeCycle规则,定时清理碎片。参考:生命周期管理

断点续传的实现依赖InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload,如果采用STS鉴权模式,请注意加上这些API所需的权限。

断点上传同样支持上传后回调通知,用法和上述普通上传回调相同。

特别注意: 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。

  1. __block NSString * uploadId = nil;
  2. OSSInitMultipartUploadRequest * init = [OSSInitMultipartUploadRequest new];
  3. init.bucketName = <bucketName>;
  4. init.objectKey = <objectKey>;
  5. // 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&InitiateMultipartUpload
  6. // append.contentType = @"";
  7. // append.contentMd5 = @"";
  8. // append.contentEncoding = @"";
  9. // append.contentDisposition = @"";
  10. // init.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil];
  11. // 先获取到用来标识整个上传事件的UploadId
  12. OSSTask * task = [client multipartUploadInit:init];
  13. [[task continueWithBlock:^id(OSSTask *task) {
  14. if (!task.error) {
  15. OSSInitMultipartUploadResult * result = task.result;
  16. uploadId = result.uploadId;
  17. } else {
  18. NSLog(@"init uploadid failed, error: %@", task.error);
  19. }
  20. return nil;
  21. }] waitUntilFinished];
  22. // 获得UploadId进行上传,如果任务失败并且可以续传,利用同一个UploadId可以上传同一文件到同一个OSS上的存储对象
  23. OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];
  24. resumableUpload.bucketName = <bucketName>;
  25. resumableUpload.objectKey = <objectKey>;
  26. resumableUpload.uploadId = uploadId;
  27. resumableUpload.partSize = 1024 * 1024;
  28. resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
  29. NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
  30. };
  31. resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your file path>];
  32. OSSTask * resumeTask = [client resumableUpload:resumableUpload];
  33. [resumeTask continueWithBlock:^id(OSSTask *task) {
  34. if (task.error) {
  35. NSLog(@"error: %@", task.error);
  36. if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) {
  37. // 该任务无法续传,需要获取新的uploadId重新上传
  38. }
  39. } else {
  40. NSLog(@"Upload file success");
  41. }
  42. return nil;
  43. }];
  44. // [resumeTask waitUntilFinished];
  45. // [resumableUpload cancel];
本文导读目录
本文导读目录
以上内容是否对您有帮助?