全部产品
弹性计算 会员服务 网络 安全 移动云 数加·大数据分析及展现 数加·大数据应用 管理与监控 云通信 阿里云办公 培训与认证 智能硬件
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 更多
对象存储 OSS

上传文件

更新时间:2018-05-27 23:59:08

进行OSS操作的基本数据单元是文件(Object)。OSS PHP SDK提供了丰富的文件上传方法,您可以通过以下方式上传文件:

  • 字符串上传
  • 文件上传
  • 追加上传
  • 分片上传

字符串上传、文件上传、追加上传的文件大小不能超过5GB,分片上传文件大小不能超过48.8TB。当文件较大时,请使用分片上传。

字符串上传

您可以使用$ossClient->putObject上传字符串到OSS,代码如下:

  1. <?php
  2. /**
  3. * 上传字符串作为object的内容
  4. *
  5. * @param OssClient $ossClient OSSClient实例
  6. * @param string $bucket 存储空间名称
  7. * @return null
  8. */
  9. function putObject($ossClient, $bucket)
  10. {
  11. $object = "oss-php-sdk-test/upload-test-object-name.txt";
  12. $content = file_get_contents(__FILE__);
  13. try{
  14. $ossClient->putObject($bucket, $object, $content);
  15. } catch(OssException $e) {
  16. printf(__FUNCTION__ . ": FAILED\n");
  17. printf($e->getMessage() . "\n");
  18. return;
  19. }
  20. print(__FUNCTION__ . ": OK" . "\n");
  21. }

文件上传

您可以使用$ossClient->uploadFile上传本地文件到OSS,代码如下:

  1. <?php
  2. /**
  3. * 上传指定的本地文件内容
  4. *
  5. * @param OssClient $ossClient OSSClient实例
  6. * @param string $bucket 存储空间名称
  7. * @return null
  8. */
  9. function uploadFile($ossClient, $bucket)
  10. {
  11. $object = "oss-php-sdk-test/upload-test-object-name.txt";
  12. $filePath = __FILE__;
  13. try{
  14. $ossClient->uploadFile($bucket, $object, $filePath);
  15. } catch(OssException $e) {
  16. printf(__FUNCTION__ . ": FAILED\n");
  17. printf($e->getMessage() . "\n");
  18. return;
  19. }
  20. print(__FUNCTION__ . ": OK" . "\n");
  21. }

追加上传

简单上传和分片上传创建的Object都是Normal类型,这种Object在上传结束之后内容就是固定的,只能读取,不能修改。如果Object内容发生了改变,只能重新上传同名的Object来覆盖之前的内容,这也是OSS和普通文件系统的一个重大区别。

OSS提供了追加上传(Append Object)的方式,在一个Object后面直接追加内容进行上传。通过这种方式上传的Object类型为Appendable,而其他方式上传的Object类型为Normal。每次追加上传的数据都能够即时可读。

追加上传字符串

您可以使用$ossClient->appendObject追加上传字符串到OSS,代码如下:

  1. <?php
  2. /**
  3. * 字符串追加上传
  4. *
  5. * @param OssClient $ossClient OSSClient实例
  6. * @param string $bucket 存储空间名称
  7. * @return null
  8. */
  9. function appendObject($ossClient, $bucket)
  10. {
  11. $object = "oss-php-sdk-test/append-test-object-name.txt";
  12. $content_array = array('Hello OSS', 'Hi OSS', 'OSS OK');
  13. try{
  14. $position = $ossClient->appendObject($bucket, $object, $content_array[0], 0);
  15. $position = $ossClient->appendObject($bucket, $object, $content_array[1], $position);
  16. $position = $ossClient->appendObject($bucket, $object, $content_array[2], $position);
  17. } catch(OssException $e) {
  18. printf(__FUNCTION__ . ": FAILED\n");
  19. printf($e->getMessage() . "\n");
  20. return;
  21. }
  22. print(__FUNCTION__ . ": OK" . "\n");
  23. }

追加上传文件

您可以使用$ossClient->appendFile追加上传本地文件到OSS,代码如下:

  1. /**
  2. * 文件追加上传
  3. *
  4. * @param OssClient $ossClient OSSClient实例
  5. * @param string $bucket 存储空间名称
  6. * @return null
  7. */
  8. function appendFile($ossClient, $bucket)
  9. {
  10. $object = "oss-php-sdk-test/append-test-File-name.txt";
  11. try{
  12. $position = $ossClient->appendFile($this->bucket, $object, __FILE__, 0);
  13. $position = $ossClient->appendFile($this->bucket, $object, __FILE__, $position);
  14. } catch(OssException $e) {
  15. printf(__FUNCTION__ . ": FAILED\n");
  16. printf($e->getMessage() . "\n");
  17. return;
  18. }
  19. print(__FUNCTION__ . ": OK" . "\n");
  20. }

说明: Appendable类型Object暂不支持copyObject方法。

分片上传

除了通过PutObject方法上传文件到OSS以外,OSS还提供了分片上传(Multipart Upload)方式。您可以在多种应用场景中使用分片上传,例如:

  • 需要支持断点续传。
  • 上传超过100MB大小的文件。
  • 网络条件较差,和OSS服务器之间的链接经常断开。
  • 上传文件之前,无法确定上传文件的大小。

分片上传分为以下三个步骤:

  1. 初始化一个分片上传事件。
    您可以通过$ossClient->initiateMultipartUpload来返回OSS服务器创建的全局唯一的Upload ID。

  2. 上传分片。
    您可以先使用$ossClient->generateMultiuploadParts对数据进行分片,再使用$ossClient->uploadPart上传分片数据。注意:

    • 每个分片被称为一个Part。每一个上传的Part都有一个标识它的号码——分片号(PartNumber,取值范围是1~10,000)。对于同一个Upload ID,分片号不但唯一标识这一块数据,也标识了这块数据在整个文件内的相对位置。
    • 除了最后一块Part以外,其他的Part最小为100KB。最后一块Part没有大小限制。
  3. 完成分片上传或取消分片上传。
    您可以使用$ossClient->completeMultipartUpload来完成对整个文件的分片上传。
    您可以使用$ossClient->abortMultipartUpload来终止分片上传事件。当一个分片上传事件被终止后,就不能再使用这个Upload ID做任何操作,已经上传的Part数据也会被删除。

以下通过一个完整的示例对分片上传的流程进行逐步解析:

  1. <?php
  2. /**
  3. * 分片上传(Multipart Upload)流程解析
  4. *
  5. * @param OssClient $ossClient OSSClient实例
  6. * @param string $bucket 存储空间名称
  7. * @throws OssException
  8. */
  9. function putObjectByRawApis($ossClient, $bucket)
  10. {
  11. $object = "test/multipart-test.txt";
  12. /**
  13. * 步骤1:初始化一个分片上传事件,获取Upload ID。
  14. */
  15. try{
  16. //Upload ID用于标识本次Multipart Upload事件。用户可以根据这个ID来发起相关的操作,如终止Multipart Upload、查询Multipart Upload等。
  17. $uploadId = $ossClient->initiateMultipartUpload($bucket, $object);
  18. } catch(OssException $e) {
  19. printf(__FUNCTION__ . ": initiateMultipartUpload FAILED\n");
  20. printf($e->getMessage() . "\n");
  21. return;
  22. }
  23. print(__FUNCTION__ . ": initiateMultipartUpload OK" . "\n");
  24. /*
  25. * 步骤2:上传分片。
  26. */
  27. $partSize = 10 * 1024 * 1024;
  28. $uploadFile = __FILE__;
  29. $uploadFileSize = filesize($uploadFile);
  30. $pieces = $ossClient->generateMultiuploadParts($uploadFileSize, $partSize);
  31. $responseUploadPart = array();
  32. $uploadPosition = 0;
  33. $isCheckMd5 = true;
  34. foreach ($pieces as $i => $piece) {
  35. $fromPos = $uploadPosition + (integer)$piece[$ossClient::OSS_SEEK_TO];
  36. $toPos = (integer)$piece[$ossClient::OSS_LENGTH] + $fromPos - 1;
  37. $upOptions = array(
  38. $ossClient::OSS_FILE_UPLOAD => $uploadFile,
  39. $ossClient::OSS_PART_NUM => ($i + 1),
  40. $ossClient::OSS_SEEK_TO => $fromPos,
  41. $ossClient::OSS_LENGTH => $toPos - $fromPos + 1,
  42. $ossClient::OSS_CHECK_MD5 => $isCheckMd5,
  43. );
  44. if ($isCheckMd5) {
  45. $contentMd5 = OssUtil::getMd5SumForFile($uploadFile, $fromPos, $toPos);
  46. $upOptions[$ossClient::OSS_CONTENT_MD5] = $contentMd5;
  47. }
  48. // 将每一分片上传到OSS。
  49. try {
  50. $responseUploadPart[] = $ossClient->uploadPart($bucket, $object, $uploadId, $upOptions);
  51. } catch(OssException $e) {
  52. printf(__FUNCTION__ . ": initiateMultipartUpload, uploadPart - part#{$i} FAILED\n");
  53. printf($e->getMessage() . "\n");
  54. return;
  55. }
  56. printf(__FUNCTION__ . ": initiateMultipartUpload, uploadPart - part#{$i} OK\n");
  57. }
  58. /*
  59. 每次上传分片之后,OSS的返回结果会包含一个 PartETag 对象,它是上传分片的ETag与分片编号(PartNumber)的组合。在后续完成分片上传的步骤中会用到它,因此我们需要将其保存起来,在第3步中使用。
  60. */
  61. $uploadParts = array();
  62. foreach ($responseUploadPart as $i => $eTag) {
  63. $uploadParts[] = array(
  64. 'PartNumber' => ($i + 1),
  65. 'ETag' => $eTag,
  66. );
  67. }
  68. /**
  69. * 步骤3:完成上传。
  70. */
  71. try {
  72. //在执行该操作时,需要提供所有有效的partETags(包括PartNumber和ETag)。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的分片验证通过后,OSS将把这些分片组合成一个完整的Object。
  73. $ossClient->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts);
  74. } catch(OssException $e) {
  75. printf(__FUNCTION__ . ": completeMultipartUpload FAILED\n");
  76. printf($e->getMessage() . "\n");
  77. return;
  78. }
  79. printf(__FUNCTION__ . ": completeMultipartUpload OK\n");
  80. }

分片上传的完整代码请参见:GitHub

分片上传文件

您可以使用$ossClient->multiuploadFile分片上传本地文件到OSS,代码如下:

  1. <?php
  2. /**
  3. * 通过Multipart上传文件
  4. *
  5. * @param OssClient $ossClient OSSClient实例
  6. * @param string $bucket 存储空间名称
  7. * @return null
  8. */
  9. function multiuploadFile($ossClient, $bucket)
  10. {
  11. $object = "test/multipart-test.txt";
  12. $file = __FILE__;
  13. try{
  14. $ossClient->multiuploadFile($bucket, $object, $file);
  15. } catch(OssException $e) {
  16. printf(__FUNCTION__ . ": FAILED\n");
  17. printf($e->getMessage() . "\n");
  18. return;
  19. }
  20. print(__FUNCTION__ . ": OK" . "\n");
  21. }

分片上传目录

您可以使用$ossClient->uploadDir分片上传本地目录到OSS,代码如下:

  1. <?php
  2. /**
  3. * 按照目录上传文件
  4. *
  5. * @param OssClient $ossClient OssClient
  6. * @param string $bucket 存储空间名称
  7. *
  8. */
  9. function uploadDir($ossClient, $bucket) {
  10. $localDirectory = ".";
  11. $prefix = "samples/codes";
  12. try {
  13. $ossClient->uploadDir($bucket, $prefix, $localDirectory);
  14. } catch(OssException $e) {
  15. printf(__FUNCTION__ . ": FAILED\n");
  16. printf($e->getMessage() . "\n");
  17. return;
  18. }
  19. printf(__FUNCTION__ . ": completeMultipartUpload OK\n");
  20. }

查看已上传的分片

您可以使用$ossClient->listParts查看已上传的分片,代码如下:

  1. /**
  2. * 查看已上传的分片
  3. *
  4. * @param OssClient $ossClient OSSClient实例
  5. * @param string $bucket 存储空间名称
  6. * @param string $uploadId upload Id
  7. * @return null
  8. */
  9. function listParts($ossClient, $bucket, $uploadId)
  10. {
  11. $object = "test/multipart-test.txt";
  12. try{
  13. $listPartsInfo = $ossClient->listParts($bucket, $object, $uploadId);
  14. foreach ($listPartsInfo->getListPart() as $partInfo) {
  15. print($partInfo->getPartNumber() . "\t" . $partInfo->getSize() . "\t" . $partInfo->getETag() . "\t" . $partInfo->getLastModified() . "\n");
  16. }
  17. } catch(OssException $e) {
  18. printf(__FUNCTION__ . ": FAILED\n");
  19. printf($e->getMessage() . "\n");
  20. return;
  21. }
  22. print(__FUNCTION__ . ": OK" . "\n");
  23. }

列举正在进行的分片上传任务

您可以使用$ossClient->listMultipartUploads列举当前正在进行中还未完成的分片上传任务,代码如下:

  1. <?php
  2. /**
  3. * 获取当前未完成的分片上传列表
  4. *
  5. * @param $ossClient OssClient
  6. * @param $bucket string
  7. */
  8. function listMultipartUploads($ossClient, $bucket) {
  9. $options = array(
  10. 'delimiter' => '/',
  11. 'max-uploads' => 100,
  12. 'key-marker' => '',
  13. 'prefix' => '',
  14. 'upload-id-marker' => ''
  15. );
  16. try {
  17. $listMultipartUploadInfo = $ossClient->listMultipartUploads($bucket, $options);
  18. } catch(OssException $e) {
  19. printf(__FUNCTION__ . ": listMultipartUploads FAILED\n");
  20. printf($e->getMessage() . "\n");
  21. return;
  22. }
  23. printf(__FUNCTION__ . ": listMultipartUploads OK\n");
  24. $listUploadInfo = $listMultipartUploadInfo->getUploads();
  25. var_dump($listUploadInfo);
  26. }

$options说明:

参数 说明
delimiter 用于对Object名字进行分组的一个字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素。
key-marker 与upload-id-marker参数一同使用来指定返回结果的起始位置。
max-uploads 限定此次返回分片上传事件的最大数目,默认值和最大值均为1000。
prefix 限定返回的object key必须以指定的prefix作为前缀。注意使用prefix查询时,返回的key中仍会包含prefix。
upload-id-marker 与key-marker参数一同使用来指定返回结果的起始位置。
本文导读目录