阿里雲團隊努力不懈,力求將最新的技術內容更快地以您最熟悉的語言呈現。本文由簡體中文內容自動轉碼而成,過程無人工干預。阿里雲不保證此自動轉碼的準確性、完整性及時效性。因轉碼造成的任何內容錯誤及因此可能帶來的損失,阿里雲概不負責,敬請見諒。本文内容請以簡體中文版本為準。
全部產品
Search
文件中心

上傳檔案

更新時間: Oct 19, 2018

在OSS中,操作的基本資料單元是檔案(Object)。OSS Python SDK提供了豐富的檔案上傳方式:

  • 簡單上傳:檔案最大不能超過5GB。
  • 追加上傳:檔案最大不能超過5GB。
  • 斷點續傳上傳:支援並發、斷點續傳、自訂分區大小。大檔案上傳推薦使用斷點續傳。最大不能超過48.8TB。
  • 分區上傳:當檔案較大時,可以使用分區上傳,最大不能超過48.8TB。

說明:各種上傳方式的適用場景請參見開發指南中的上傳檔案。

上傳過程中,您還可以設定檔案元資訊

簡單上傳

簡單上傳的完整代碼請參見GitHub

上傳字元串

以下代碼用於上傳字元串:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  7. )
  8. func main() {
  9. // 建立OSSClient執行個體。
  10. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  11. if err != nil {
  12. fmt.Println("Error:", err)
  13. os.Exit(-1)
  14. }
  15. // 獲取儲存空間。
  16. bucket, err := client.Bucket("<yourBucketName>")
  17. if err != nil {
  18. fmt.Println("Error:", err)
  19. os.Exit(-1)
  20. }
  21. // 上傳字元串。
  22. err = bucket.PutObject("<yourObjectName>", strings.NewReader("yourObjectValue"))
  23. if err != nil {
  24. fmt.Println("Error:", err)
  25. os.Exit(-1)
  26. }
  27. }

上傳Byte數組

以下代碼用於上傳Byte數組:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "bytes"
  6. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  7. )
  8. func main() {
  9. // 建立OSSClient執行個體。
  10. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  11. if err != nil {
  12. fmt.Println("Error:", err)
  13. os.Exit(-1)
  14. }
  15. // 獲取儲存空間。
  16. bucket, err := client.Bucket("<yourBucketName>")
  17. if err != nil {
  18. fmt.Println("Error:", err)
  19. os.Exit(-1)
  20. }
  21. // 上傳Byte數組。
  22. err = bucket.PutObject("<yourObjectName>", bytes.NewReader([]byte("yourObjectValueByteArrary")))
  23. if err != nil {
  24. fmt.Println("Error:", err)
  25. os.Exit(-1)
  26. }
  27. }

上傳檔案流

以下代碼用於上傳檔案流:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. func main() {
  8. // 建立OSSClient執行個體。
  9. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  10. if err != nil {
  11. fmt.Println("Error:", err)
  12. os.Exit(-1)
  13. }
  14. // 獲取儲存空間。
  15. bucket, err := client.Bucket("<yourBucketName>")
  16. if err != nil {
  17. fmt.Println("Error:", err)
  18. os.Exit(-1)
  19. }
  20. // 讀取本地檔案。
  21. fd, err := os.Open("<yourLocalFile>")
  22. if err != nil {
  23. fmt.Println("Error:", err)
  24. os.Exit(-1)
  25. }
  26. defer fd.Close()
  27. // 上傳檔案流。
  28. err = bucket.PutObject("<yourObjectName>", fd)
  29. if err != nil {
  30. fmt.Println("Error:", err)
  31. os.Exit(-1)
  32. }
  33. }

上傳本地檔案

以下代碼用於上傳本地檔案:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. func main() {
  8. // 建立OSSClient執行個體。
  9. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  10. if err != nil {
  11. fmt.Println("Error:", err)
  12. os.Exit(-1)
  13. }
  14. // 獲取儲存空間。
  15. bucket, err := client.Bucket("<yourBucketName>")
  16. if err != nil {
  17. fmt.Println("Error:", err)
  18. os.Exit(-1)
  19. }
  20. // 上傳本地檔案。
  21. err = bucket.PutObjectFromFile("<yourObjectName>", "<yourLocalFile>")
  22. if err != nil {
  23. fmt.Println("Error:", err)
  24. os.Exit(-1)
  25. }
  26. }

追加上傳

追加類型的檔案(Append Object)暫時不支援copyObject操作。檔案不存在時,調用AppendObject會建立一個可追加的檔案;檔案存在時,調用AppendObject會向檔案末尾追加內容。

以下代碼用於追加上傳檔案:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  7. )
  8. func main() {
  9. // 建立OSSClient執行個體。
  10. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  11. if err != nil {
  12. fmt.Println("Error:", err)
  13. os.Exit(-1)
  14. }
  15. // 獲取儲存空間。
  16. bucket, err := client.Bucket("<yourBucketName>")
  17. if err != nil {
  18. fmt.Println("Error:", err)
  19. os.Exit(-1)
  20. }
  21. var nextPos int64 = 0
  22. // 第一次追加的位置是0,傳回值為下一次追加的位置。後續追加的位置是追加前檔案的長度。
  23. nextPos, err = bucket.AppendObject("<yourObjectName>", strings.NewReader("YourObjectAppendValue1"), nextPos)
  24. if err != nil {
  25. fmt.Println("Error:", err)
  26. os.Exit(-1)
  27. }
  28. // 第二次追加。
  29. nextPos, err = bucket.AppendObject("<yourObjectName>", strings.NewReader("YourObjectAppendValue2"), nextPos)
  30. if err != nil {
  31. fmt.Println("Error:", err)
  32. os.Exit(-1)
  33. }
  34. // 您可以進行多次Append。
  35. }

第一次追加(即開始位置是0的追加)可以指定檔案元資訊;後續追加不能指定檔案元資訊。

  1. // 第一次追加指定檔案元資訊。
  2. nextPos, err = bucket.AppendObject("<yourObjectName>", strings.NewReader("YourObjectValue"), 0, oss.Meta("MyProp", "MyPropVal"))
  3. if err != nil {
  4. fmt.Println("Error:", err)
  5. os.Exit(-1)
  6. }

斷點續傳上傳

斷點續傳上傳是指將要上傳的檔案分成若干個分區(Part)分別上傳,所有分區都上傳完成後,將所有分區合并成完整的檔案,完成整個檔案的上傳。在上傳的過程中會在Checkpoint檔案中記錄當前上傳的進度資訊,如果上傳過程中某一分區上傳失敗,再次上傳時會從Checkpoint檔案中記錄的點繼續上傳,從而達到斷點續傳的效果。上傳完成後,Checkpoint檔案會被刪除。

說明:

  • SDK會將上傳的中間狀態資訊記錄在Checkpoint檔案中,所以要確保程式對Checkpoint檔案有寫入權限。Checkpoint攜帶了校驗資訊,請不要修改。如果Checkpoint檔案損壞則會重新上傳所有分區。
  • 如果上傳過程中本地檔案發生了改變,則會重新上傳所有分區。

您可以使用Bucket.UploadFile實現斷點續傳。可設定的參數如下:

參數 說明
objectKey 上傳到OSS的檔案名稱。
filePath 待上傳的本地檔案路徑。
partSize 分區上傳大小,取值範圍為100KB~5GB。
options 可選項,包括:
- Routines:指定分區上傳的並發數。預設是1,即不使用並發上傳。
- Checkpoint:指定是否開啟斷點續傳功能以及設定Checkpoint檔案。預設關閉斷點續傳功能。例如oss.Checkpoint(true, ""), 表示開啟斷點續傳功能,並且Checkpoint檔案為與本地檔案同目錄下的file.cp,其中file是本地檔案名稱。您也可以使用oss.Checkpoint(true, "your-cp-file.cp")指定Checkpoint檔案。
- 其它元資訊:請參見設定檔案元資訊

以下代碼用於斷點續傳上傳:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. func main() {
  8. // 建立OSSClient執行個體。
  9. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  10. if err != nil {
  11. fmt.Println("Error:", err)
  12. os.Exit(-1)
  13. }
  14. // 獲取儲存空間。
  15. bucket, err := client.Bucket("<yourBucketName>")
  16. if err != nil {
  17. fmt.Println("Error:", err)
  18. os.Exit(-1)
  19. }
  20. // 分區大小100K,3個協程並發上傳分區,使用斷點續傳。
  21. // 其中"<yourObjectName>"為objectKey, "LocalFile"為filePath,100*1024為partSize。
  22. err = bucket.UploadFile("<yourObjectName>", "LocalFile", 100*1024, oss.Routines(3), oss.Checkpoint(true, ""))
  23. if err != nil {
  24. fmt.Println("Error:", err)
  25. os.Exit(-1)
  26. }
  27. }

分區上傳

分區上傳(Multipart Upload)分為以下三個步驟:

  1. 初始化一個分區上傳事件。
    調用Bucket.InitiateMultipartUpload方法返回OSS建立的全域唯一的uploadId。

  2. 上傳分區。
    調用Bucket.UploadPart方法上傳分區資料。需要注意:

    • 對於同一個uploadId,分區號(partNumber)標識了該分區在整個檔案內的相對位置。如果使用同一個分區號上傳了新的資料,那麼OSS上這個分區已有的資料將會被覆蓋。
    • OSS將收到的分區資料的MD5值放在ETag頭內返回給使用者。
    • SDK自動化佈建Content-MD5。OSS計算上傳資料的MD5值,並與SDK計算的MD5值比較,如果不一致則返回InvalidDigest錯誤碼。
  3. 完成分區上傳。
    所有分區上傳完成後,調用Bucket.CompleteMultipartUpload方法將所有分區合并成完整的檔案。

以下通過一個完整的樣本對分區上傳的流程進行逐步解析:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. func main() {
  8. // 建立OSSClient執行個體。
  9. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  10. if err != nil {
  11. fmt.Println("Error:", err)
  12. os.Exit(-1)
  13. }
  14. bucketName := "<yourBucketName>"
  15. objectName := "<yourObjectName>"
  16. locaFilename := "<yourLocalFilename>"
  17. // 獲取儲存空間。
  18. bucket, err := client.Bucket(bucketName)
  19. if err != nil {
  20. fmt.Println("Error:", err)
  21. os.Exit(-1)
  22. }
  23. chunks, err := oss.SplitFileByPartNum(locaFilename, 3)
  24. fd, err := os.Open(locaFilename)
  25. defer fd.Close()
  26. // 步驟1:初始化一個分區上傳事件。
  27. imur, err := bucket.InitiateMultipartUpload(objectName)
  28. // 步驟2:上傳分區。
  29. var parts []oss.UploadPart
  30. for _, chunk := range chunks {
  31. fd.Seek(chunk.Offset, os.SEEK_SET)
  32. // 對每個分區調用UploadPart方法上傳。
  33. part, err := bucket.UploadPart(imur, fd, chunk.Size, chunk.Number)
  34. if err != nil {
  35. fmt.Println("Error:", err)
  36. os.Exit(-1)
  37. }
  38. parts = append(parts, part)
  39. }
  40. // 步驟3:完成分區上傳。
  41. cmur, err := bucket.CompleteMultipartUpload(imur, parts)
  42. if err != nil {
  43. fmt.Println("Error:", err)
  44. os.Exit(-1)
  45. }
  46. fmt.Println("cmur:", cmur)
  47. }

取消分區上傳

以下代碼用於取消分區上傳:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. func main() {
  8. // 建立OSSClient執行個體。
  9. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  10. if err != nil {
  11. fmt.Println("Error:", err)
  12. os.Exit(-1)
  13. }
  14. // 獲取儲存空間。
  15. bucket, err := client.Bucket("<yourBucketName>")
  16. if err != nil {
  17. fmt.Println("Error:", err)
  18. os.Exit(-1)
  19. }
  20. // 初始化一個分區上傳事件。
  21. imur, err := bucket.InitiateMultipartUpload("<yourObjectName>")
  22. if err != nil {
  23. fmt.Println("Error:", err)
  24. os.Exit(-1)
  25. }
  26. // 取消分區上傳。
  27. err = bucket.AbortMultipartUpload(imur)
  28. if err != nil {
  29. fmt.Println("Error:", err)
  30. os.Exit(-1)
  31. }
  32. }

列舉所有已上傳的分區

以下代碼用於列舉某個分區上傳事件的所有已經上傳成功的分區。

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. func main() {
  8. // 建立OSSClient執行個體。
  9. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  10. if err != nil {
  11. fmt.Println("Error:", err)
  12. os.Exit(-1)
  13. }
  14. // 獲取儲存空間。
  15. bucket, err := client.Bucket("<yourBucketName>")
  16. if err != nil {
  17. fmt.Println("Error:", err)
  18. os.Exit(-1)
  19. }
  20. // 初始化一個分區上傳事件。
  21. imur, err := bucket.InitiateMultipartUpload("<yourObjectName>")
  22. if err != nil {
  23. fmt.Println("Error:", err)
  24. os.Exit(-1)
  25. }
  26. // 列舉所有已上傳的分區。
  27. lsRes, err := bucket.ListUploadedParts(imur)
  28. if err != nil {
  29. fmt.Println("Error:", err)
  30. os.Exit(-1)
  31. }
  32. fmt.Println("Parts:", lsRes.UploadedParts)
  33. }

列舉分區上傳事件

您可以使用Bucket.ListMultipartUploads方法列出所有執行中的分區上傳事件,即已初始化但尚未完成或已取消的分區上傳事件。可設定的參數如下:

參數 說明
Delimiter 用於對Object名字進行分組的字元。所有名字包含指定的首碼且第一次出現delimiter字元之間的object作為一組元素。
MaxUploads 限定此次返回分區上傳事件的最大數目,預設值和最大值均為1000。
KeyMarker 所有檔案名稱的字母序大於keyMarker參數值的分區上傳事件。
Prefix 限定返回的檔案名稱必須以指定的prefix作為首碼。注意使用prefix查詢時,返回的檔案名稱中仍會包含prefix。

使用預設參數

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. func main() {
  8. // 建立OSSClient執行個體。
  9. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  10. if err != nil {
  11. fmt.Println("Error:", err)
  12. os.Exit(-1)
  13. }
  14. // 獲取儲存空間。
  15. bucket, err := client.Bucket("<yourBucketName>")
  16. if err != nil {
  17. fmt.Println("Error:", err)
  18. os.Exit(-1)
  19. }
  20. // 列舉所有分區上傳事件。
  21. lsRes, err := bucket.ListMultipartUploads()
  22. if err != nil {
  23. fmt.Println("Error:", err)
  24. os.Exit(-1)
  25. }
  26. fmt.Println("Uploads:", lsRes.Uploads)
  27. }

指定首碼

  1. lsRes, err := bucket.ListMultipartUploads(oss.Prefix("<yourObjectNamePrefix>"))
  2. if err != nil {
  3. fmt.Println("Error:", err)
  4. os.Exit(-1)
  5. }
  6. fmt.Println("Uploads:", lsRes.Uploads)

指定最多返回100條結果資料

  1. lsRes, err := bucket.ListMultipartUploads(oss.MaxUploads(100))
  2. if err != nil {
  3. fmt.Println("Error:", err)
  4. os.Exit(-1)
  5. }
  6. fmt.Println("Uploads:", lsRes.Uploads)

同時指定首碼和最大返回條數

  1. lsRes, err := bucket.ListMultipartUploads(oss.Prefix("<yourObjectNamePrefix>"), oss.MaxUploads(100))
  2. if err != nil {
  3. fmt.Println("Error:", err)
  4. os.Exit(-1)
  5. }
  6. fmt.Println("Uploads:", lsRes.Uploads)

進度條

進度條用於指示上傳或下載的進度。下面的代碼以Bucket.PutObjectFromFile方法為例,介紹如何使用進度條。

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/aliyun/aliyun-oss-go-sdk/oss"
  6. )
  7. // 定義進度條監聽器。
  8. type OssProgressListener struct {
  9. }
  10. // 定義進度變更事件處理函數。
  11. func (listener *OssProgressListener) ProgressChanged(event *oss.ProgressEvent) {
  12. switch event.EventType {
  13. case oss.TransferStartedEvent:
  14. fmt.Printf("Transfer Started, ConsumedBytes: %d, TotalBytes %d.\n",
  15. event.ConsumedBytes, event.TotalBytes)
  16. case oss.TransferDataEvent:
  17. fmt.Printf("\rTransfer Data, ConsumedBytes: %d, TotalBytes %d, %d%%.",
  18. event.ConsumedBytes, event.TotalBytes, event.ConsumedBytes*100/event.TotalBytes)
  19. case oss.TransferCompletedEvent:
  20. fmt.Printf("\nTransfer Completed, ConsumedBytes: %d, TotalBytes %d.\n",
  21. event.ConsumedBytes, event.TotalBytes)
  22. case oss.TransferFailedEvent:
  23. fmt.Printf("\nTransfer Failed, ConsumedBytes: %d, TotalBytes %d.\n",
  24. event.ConsumedBytes, event.TotalBytes)
  25. default:
  26. }
  27. }
  28. func main() {
  29. // 建立OSSClient執行個體。
  30. client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  31. if err != nil {
  32. fmt.Println("Error:", err)
  33. os.Exit(-1)
  34. }
  35. bucketName := "<yourBucketName>"
  36. objectName := "<yourObjectName>"
  37. localFile := "<yourLocalFile>"
  38. // 獲取儲存空間。
  39. bucket, err := client.Bucket(bucketName)
  40. if err != nil {
  41. fmt.Println("Error:", err)
  42. os.Exit(-1)
  43. }
  44. // 帶進度條的上傳。
  45. err = bucket.PutObjectFromFile(objectName, localFile, oss.Progress(&OssProgressListener{}))
  46. if err != nil {
  47. fmt.Println("Error:", err)
  48. os.Exit(-1)
  49. }
  50. }