全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网
对象存储 OSS

上传文件

更新时间:2017-11-15 10:56:18

简单上传本地文件

调用同步接口上传

  1. // 构造上传请求
  2. PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. // 文件元信息的设置是可选的
  4. // ObjectMetadata metadata = new ObjectMetadata();
  5. // metadata.setContentType("application/octet-stream"); // 设置content-type
  6. // metadata.setContentMD5(BinaryUtil.calculateBase64Md5(uploadFilePath)); // 校验MD5
  7. // put.setMetadata(metadata);
  8. try {
  9. PutObjectResult putResult = oss.putObject(put);
  10. Log.d("PutObject", "UploadSuccess");
  11. Log.d("ETag", putResult.getETag());
  12. Log.d("RequestId", putResult.getRequestId());
  13. } catch (ClientException e) {
  14. // 本地异常如网络异常等
  15. e.printStackTrace();
  16. } catch (ServiceException e) {
  17. // 服务异常
  18. Log.e("RequestId", e.getRequestId());
  19. Log.e("ErrorCode", e.getErrorCode());
  20. Log.e("HostId", e.getHostId());
  21. Log.e("RawMessage", e.getRawMessage());
  22. }

注意:在Android中,不能在UI线程调用同步接口,只能在子线程调用,否则将出现异常。如果希望直接在UI线程中上传,请使用异步接口。

调用异步接口上传

  1. // 构造上传请求
  2. PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. // 异步上传时可以设置进度回调
  4. put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
  5. @Override
  6. public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
  7. Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
  8. }
  9. });
  10. OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  11. @Override
  12. public void onSuccess(PutObjectRequest request, PutObjectResult result) {
  13. Log.d("PutObject", "UploadSuccess");
  14. Log.d("ETag", result.getETag());
  15. Log.d("RequestId", result.getRequestId());
  16. }
  17. @Override
  18. public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
  19. // 请求异常
  20. if (clientExcepion != null) {
  21. // 本地异常如网络异常等
  22. clientExcepion.printStackTrace();
  23. }
  24. if (serviceException != null) {
  25. // 服务异常
  26. Log.e("ErrorCode", serviceException.getErrorCode());
  27. Log.e("RequestId", serviceException.getRequestId());
  28. Log.e("HostId", serviceException.getHostId());
  29. Log.e("RawMessage", serviceException.getRawMessage());
  30. }
  31. }
  32. });
  33. // task.cancel(); // 可以取消任务
  34. // task.waitUntilFinished(); // 可以等待任务完成

简单上传二进制byte[]数组

  1. byte[] uploadData = new byte[100 * 1024];
  2. new Random().nextBytes(uploadData);
  3. // 构造上传请求
  4. PutObjectRequest put = new PutObjectRequest(testBucket, testObject, uploadData);
  5. try {
  6. PutObjectResult putResult = oss.putObject(put);
  7. Log.d("PutObject", "UploadSuccess");
  8. Log.d("ETag", putResult.getETag());
  9. Log.d("RequestId", putResult.getRequestId());
  10. } catch (ClientException e) {
  11. // 本地异常如网络异常等
  12. e.printStackTrace();
  13. } catch (ServiceException e) {
  14. // 服务异常
  15. Log.e("RequestId", e.getRequestId());
  16. Log.e("ErrorCode", e.getErrorCode());
  17. Log.e("HostId", e.getHostId());
  18. Log.e("RawMessage", e.getRawMessage());
  19. }

上传到文件目录

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

在上传文件时,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。

注意:OSS路径默认是”根目录”,不需要以’/‘开头。

上传Content-Type设置

在Web服务中Content-Type用来设定文件的类型,决定以什么形式、什么编码读取这个文件。某些情况下,对于上传的文件需要设定Content-Type,否则文件不能以自己需要的形式和编码来读取。使用SDK上传文件时,如果不指定Content-Type,SDK会帮您根据后缀自动添加Content-Type。

  1. // 构造上传请求
  2. PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. ObjectMetadata metadata = new ObjectMetadata();
  4. // 指定Content-Type
  5. metadata.setContentType("application/octet-stream");
  6. // user自定义metadata
  7. metadata.addUserMetadata("x-oss-meta-name1", "value1");
  8. put.setMetadata(metadata);
  9. OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  10. ...
  11. });

MD5校验设置

如果要校验上传到OSS的文件和本地文件是否一致,可以在上传文件时携带文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器接收到的文件MD5值和Content-MD5一致时才可以上传成功,从而保证上传数据的一致性。

  1. // 构造上传请求
  2. PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. ObjectMetadata metadata = new ObjectMetadata();
  4. metadata.setContentType("application/octet-stream");
  5. try {
  6. // 设置Md5以便校验
  7. metadata.setContentMD5(BinaryUtil.calculateBase64Md5("<uploadFilePath>")); // 如果是从文件上传
  8. // metadata.setContentMD5(BinaryUtil.calculateBase64Md5(byte[])); // 如果是上传二进制数据
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. }
  12. put.setMetadata(metadata);
  13. OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  14. ...
  15. });

Append Object 追加上传

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

  1. AppendObjectRequest append = new AppendObjectRequest(testBucket, testObject, uploadFilePath);
  2. ObjectMetadata metadata = new ObjectMetadata();
  3. metadata.setContentType("application/octet-stream");
  4. append.setMetadata(metadata);
  5. // 设置追加位置
  6. append.setPosition(0);
  7. append.setProgressCallback(new OSSProgressCallback<AppendObjectRequest>() {
  8. @Override
  9. public void onProgress(AppendObjectRequest request, long currentSize, long totalSize) {
  10. Log.d("AppendObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
  11. }
  12. });
  13. OSSAsyncTask task = oss.asyncAppendObject(append, new OSSCompletedCallback<AppendObjectRequest, AppendObjectResult>() {
  14. @Override
  15. public void onSuccess(AppendObjectRequest request, AppendObjectResult result) {
  16. Log.d("AppendObject", "AppendSuccess");
  17. Log.d("NextPosition", "" + result.getNextPosition());
  18. }
  19. @Override
  20. public void onFailure(AppendObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
  21. // 异常处理
  22. }
  23. });

用户使用Append方式上传,关键要对Position这个参数进行正确的设置:

  • 当用户创建一个Appendable Object时,追加位置设为0。

  • 当对Appendable Object进行内容追加时,追加位置设为Object当前长度。有两种方式获取该Object长度:

    • 通过上传追加后的返回内容获取。
    • 通过head object获取文件长度。

上传后回调通知

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

具体说明参考:Callback

代码示例:

  1. PutObjectRequest put = new PutObjectRequest(testBucket, testObject, uploadFilePath);
  2. put.setCallbackParam(new HashMap<String, String>() {
  3. {
  4. put("callbackUrl", "110.75.82.106/callback");
  5. put("callbackHost", "oss-cn-hangzhou.aliyuncs.com");
  6. put("callbackBodyType", "application/json");
  7. put("callbackBody", "{\"mimeType\":${mimeType},\"size\":${size}}");
  8. }
  9. });
  10. OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
  11. @Override
  12. public void onSuccess(PutObjectRequest request, PutObjectResult result) {
  13. Log.d("PutObject", "UploadSuccess");
  14. // 只有设置了servercallback,这个值才有数据
  15. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  16. Log.d("servercallback", serverCallbackReturnJson);
  17. }
  18. @Override
  19. public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
  20. // 异常处理
  21. }
  22. });

如果需要支持自定义参数,参考如下设置:

  1. put.setCallbackParam(new HashMap<String, String>() {
  2. {
  3. put("callbackUrl", "http://182.92.192.125/leibin/notify.php");
  4. put("callbackHost", "oss-cn-hangzhou.aliyuncs.com");
  5. put("callbackBodyType", "application/json");
  6. put("callbackBody", "{\"object\":${object},\"size\":${size},\"my_var1\":${x:var1},\"my_var2\":${x:var2}}");
  7. }
  8. });
  9. put.setCallbackVars(new HashMap<String, String>() {
  10. {
  11. put("x:var1", "value1");
  12. put("x:var2", "value2");
  13. }
  14. });

断点续传

特别注意

  • 断点续传暂时只支持上传本地文件。

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

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

在上传前,可以指定断点记录的保存文件夹。若不进行此项设置,断点上传只在本次上传生效,某个分片因为网络原因等上传失败时会进行重试,避免整个大文件重新上传,节省重试时间和耗用流量。如果设置了断点记录的保存文件夹,如果任务失败,在下次重新启动任务,上传同一文件到同一Bucket、Object时,将从断点记录处继续上传。

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

说明:

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

  • 断点续传也支持上传后回调通知,用法和上述普通上传回调通知一致。

  • 断点续传已经默认开启每个分片上传时的Md5校验,请勿重复在request中设置Content-Md5头部。

不在本地持久保存断点记录的调用方式

  1. // 创建断点上传请求
  2. ResumableUploadRequest request = new ResumableUploadRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. // 设置上传过程回调
  4. request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
  5. @Override
  6. public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
  7. Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
  8. }
  9. });
  10. // 异步调用断点上传
  11. OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
  12. @Override
  13. public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
  14. Log.d("resumableUpload", "success!");
  15. }
  16. @Override
  17. public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
  18. // 异常处理
  19. }
  20. });
  21. // resumableTask.waitUntilFinished(); // 可以等待直到任务完成

在本地持久保存断点记录的调用方式

  1. String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
  2. File recordDir = new File(recordDirectory);
  3. // 要保证目录存在,如果不存在则主动创建
  4. if (!recordDir.exists()) {
  5. recordDir.mkdirs();
  6. }
  7. // 创建断点上传请求,参数中给出断点记录文件的保存位置,需是一个文件夹的绝对路径
  8. ResumableUploadRequest request = new ResumableUploadRequest("<bucketName>", "<objectKey>", "<uploadFilePath>", recordDirectory);
  9. // 设置上传过程回调
  10. request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
  11. @Override
  12. public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
  13. Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
  14. }
  15. });
  16. OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
  17. @Override
  18. public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
  19. Log.d("resumableUpload", "success!");
  20. }
  21. @Override
  22. public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
  23. // 异常处理
  24. }
  25. });
  26. // resumableTask.waitUntilFinished();

进行取消时是否需要删除记录文件的调用方式

  1. //调用OSSAsyncTask cancel()方法时是否需要删除断点记录文件的设置
  2. String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
  3. File recordDir = new File(recordDirectory);
  4. // 要保证目录存在,如果不存在则主动创建
  5. if (!recordDir.exists()) {
  6. recordDir.mkdirs();
  7. }
  8. // 创建断点上传请求,参数中给出断点记录文件的保存位置,需是一个文件夹的绝对路径
  9. ResumableUploadRequest request = new ResumableUploadRequest("<bucketName>", "<objectKey>", "<uploadFilePath>", recordDirectory);
  10. //设置false,取消时,不删除断点记录文件,如果不进行设置,默认true,是会删除断点记录文件,下次再进行上传时会重新上传。
  11. request.setDeleteUploadOnCancelling(false);
  12. // 设置上传过程回调
  13. request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
  14. @Override
  15. public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
  16. Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
  17. }
  18. });
  19. OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
  20. @Override
  21. public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
  22. Log.d("resumableUpload", "success!");
  23. }
  24. @Override
  25. public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
  26. // 异常处理
  27. }
  28. });
  29. // resumableTask.waitUntilFinished();
本文导读目录