edit-icon download-icon

Upload objects

Last Updated: Feb 07, 2018

OSS mobile SDK uploads files in the following ways: simple upload, content appended upload, multipart upload, and resumable upload.

Upload local files in a simple mode

Upload a local file by calling synchronous APIs:

  1. // Construct an upload request
  2. PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. // Configure file metadata (optional)
  4. // ObjectMetadata metadata = new ObjectMetadata();
  5. // metadata.setContentType("application/octet-stream"); // Set the Content-Type
  6. // metadata.setContentMD5(BinaryUtil.calculateBase64Md5(uploadFilePath)); // Verify the 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. // Local exception, such as a network exception
  15. e.printStackTrace();
  16. } catch (ServiceException e) {
  17. // Service exception
  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. }

Note: In Android, synchronous APIs can be called only in subthreads. An exception occurs if a synchronous API is called in the UI thread. Use an asynchronous API if you must upload a file in the UI thread.

Upload a local file by calling asynchronous APIs:

  1. // Construct an upload request
  2. PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. // You can set progress callback during the asynchronous upload
  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. // Request exception
  20. if (clientExcepion != null) {
  21. // Local exception, such as a network exception
  22. clientExcepion.printStackTrace();
  23. }
  24. if (serviceException != null) {
  25. // Service exception
  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(); // You can cancel the task
  34. // task.waitUntilFinished(); // Wait until the task is complete

Upload a binary byte [] array in a simple mode

  1. byte[] uploadData = new byte[100 * 1024];
  2. new Random().nextBytes(uploadData);
  3. // Construct an upload request
  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. // Local exception, such as a network exception
  12. e.printStackTrace();
  13. } catch (ServiceException e) {
  14. // Service exception
  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. }

Upload a file to a directory

OSS does not use folders. All elements are stored as files. But it offers a mode for you to create a simulated folder. When you create a simulated folder, you actually create a file ended with a slash (/) in its name. This file can be uploaded and downloaded as a normal file, but the file whose name ends with a slash (/) is displayed as a folder in the OSS console.

When you upload a file, if you write the ObjectKey as "folder/subfolder/file", you are simulating uploading the file to the file object under the folder/subfolder/.

Note: The default OSS path is the “root directory” and does not need to start with a slash (/).

Set the Content-Type for uploaded files

In web services, the Content-Type defines the type of a file and determines the mode and encoding used to read the file. In some cases, you must set the Content-Type for the file to be uploaded. Otherwise, the file cannot be read in the expected mode and encoding. When you use the OSS Android SDKs to upload a file without configuring the Content-Type, the SDKs add the Content-Type automatically according to the file name suffix.

  1. // Construct an upload request
  2. PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. ObjectMetadata metadata = new ObjectMetadata();
  4. // Specify the Content-Type
  5. metadata.setContentType("application/octet-stream");
  6. // User-defined 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. });

Append Object

Append Object is used to upload files in the appending mode. The type of the objects created with Append Object is Appendable Object, and the type of the objects uploaded with Put Object is 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. // Set the position for appending
  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. // Exception handling
  22. }
  23. });

To use the Append upload method, you must set the Position parameter correctly:

  • When you create an Appendable Object, the position for appending is 0.

  • To append contents to an Appendable Object, the position for appending is the object’s current length. You can get the length of an object by using the following methods:

    • Get the length from the returned content of append upload.
    • Get the length using the head object.

Callback notification after the upload

When you upload an object on the client, you can configure the OSS server to notify your business server of the successful processing of upload requests. After the server receives the callback, it returns the callback result to the client. Compared with the simple upload, upload with callback notifications requires the client to wait a longer time to process a callback request and response.

For more information, see Callback.

Sample codes:

  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. // This value is not empty only when the "Server Callback" is specified.
  15. String serverCallbackReturnJson = result.getServerCallbackReturnBody();
  16. Log.d("servercallback", serverCallbackReturnJson);
  17. }
  18. @Override
  19. public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
  20. // Exception handling
  21. }
  22. });

The following settings are required if you want to support the custom parameters:

  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. });

Multipart upload

Due to limited space, for more information about multipart upload, see: Multipart Upload.

Resumable upload

Note:

  • Currently, this feature only supports local file upload.

  • Resumable upload is not recommended for uploading small- and medium-sized files from a mobile device. Resumable upload adopts the Multipart Upload method, which initiates multiple network requests for uploading a single file, reducing the upload efficiency.**

In a wireless network connection, it usually takes a relatively long time to upload a large file. The upload may fail due to poor network connectivity or network switching. In this case, the entire file needs to be uploaded again. To address this problem, the SDK provides the resumable upload feature.

Before uploading, you can specify the folder for storing resumable upload records. If you do not specify the folder, resumable upload takes effect only for the current upload task. When a part of a large file fails to be uploaded due to network issues, only this part is uploaded again, instead of the entire file, thus saving the time and reducing the traffic consumption. If you specify the folder, when you restart a previously failed upload task to upload the same file to an object stored in a bucket as before, the upload starts from the content specified in the resumable upload record.

When a resumable upload task fails and is not resumed for a long time, the uploaded parts may become useless parts on OSS. In this case, you can set the lifecycle rule for the bucket to clear parts in a timely manner. See Lifecycle Management.

Note:

  • Resumable upload depends on InitMultipartUpload/UploadPart/ListParts/CompleteMultipartUpload/AbortMultipartUpload. If you use the STS authentication mode, add the permissions required to use the APIs.

  • Resumable upload supports callback notifications after the upload in the same usage as the preceding normal upload callback notifications.

  • Resumable upload has enabled the MD5 verification by default during each part upload. You do not need to set the Content-Md5 header again in the request.

The following codes use a call method whereby resumable upload records are not permanently stored on the local device:

  1. // Create a resumable upload request
  2. ResumableUploadRequest request = new ResumableUploadRequest("<bucketName>", "<objectKey>", "<uploadFilePath>");
  3. // Set the callback during the uploading process
  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. // Asynchronous calls of the resumable upload
  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. // Exception handling
  19. }
  20. });
  21. // resumableTask.waitUntilFinished(); // Wait until the task is complete

The following codes use a call method whereby resumable upload records are permanently stored on the local device:

  1. String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
  2. File recordDir = new File(recordDirectory);
  3. // The directory must exist. Otherwise, it is automatically created.
  4. if (!recordDir.exists()) {
  5. recordDir.mkdirs();
  6. }
  7. // Create a resumable upload request with a parameter indicating the absolute path of the folder for storing resumable upload records
  8. ResumableUploadRequest request = new ResumableUploadRequest("<bucketName>", "<objectKey>", "<uploadFilePath>", recordDirectory);
  9. // Set the callback during the uploading process
  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. // Exception handling
  24. }
  25. });
  26. // resumableTask.waitUntilFinished();

Resumable upload implementation:

  1. //Whether to delete the settings of resumable upload records when the OSSAsyncTask cancel() is called
  2. String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
  3. File recordDir = new File(recordDirectory);
  4. // The directory must exist. Otherwise, it is automatically created.
  5. if (!recordDir.exists()) {
  6. recordDir.mkdirs();
  7. }
  8. // Create a resumable upload request with a parameter indicating the absolute path of the folder for storing resumable upload records
  9. ResumableUploadRequest request = new ResumableUploadRequest("<bucketName>", "<objectKey>", "<uploadFilePath>", recordDirectory);
  10. //If it is set as false, during the cancellation,the resumable upload records are not deleted. If you do not configure it and the default value is true, the resumable upload records are deleted and the files are uploaded again during the next upload.
  11. request.setDeleteUploadOnCancelling(false);
  12. // Set the callback during the uploading process
  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. // Exception handling
  27. }
  28. });
  29. // resumableTask.waitUntilFinished();

Data integrity verification

OSS SDK provides an end-to-end data integrity verification feature based on MD5 and CRC64 to handle the complexities in mobile network environments.

MD5 verification

You must provide the Content-MD5 value to the file during the uploading. Then, the OSS server performs the MD5 verification. The uploading can be successful only when the MD5 value of the file received by the OSS server is equal to the MD5 value provided during uploading, thus guaranteeing the integrity of uploaded data.

  1. OSSPutObjectRequest * request = [OSSPutObjectRequest new];
  2. request.bucketName = BUCKET_NAME;
  3. ...
  4. request.contentMd5 = [OSSUtil fileMD5String:filepath];

CRC verification

Compared with MD5, CRC64 can calculate the CRC value while uploading files.

  1. // Construct an upload request
  2. OSSPutObjectRequest * request = [OSSPutObjectRequest new];
  3. request.bucketName = OSS_BUCKET_PRIVATE;
  4. ///....
  5. request.crcFlag = OSSRequestCRCOpen;
  6. // Enable CRC verification If the data is inconsistent during transmission, OSSClientErrorCodeInvalidCRC is thrown.
  7. OSSTask * task = [_client putObject:request];
  8. [[task continueWithBlock:^id(OSSTask *task) {
  9. // If CRC verification fails, an error is reported
  10. XCTAssertNil(task.error);
  11. return nil;
  12. }] waitUntilFinished];
Thank you! We've received your feedback.