使用Go语言上传Azure的Blob。

huangapple go评论118阅读模式
英文:

upload blobs with go - azure

问题

我正在构建一个使用Go和Gin编写的API,用于将Blob上传到Azure Storage。以下是代码:

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "net/url"
  8. "github.com/Azure/azure-storage-blob-go/azblob"
  9. "github.com/gin-gonic/gin"
  10. )
  11. func main() {
  12. router := gin.Default()
  13. router.POST("/upload", func(c *gin.Context) {
  14. accountName := "blablabla"
  15. accountKey := "mykey"
  16. containerName := "testblabla"
  17. blobName := c.PostForm("blobName")
  18. credential, err := azblob.NewSharedKeyCredential(accountName, accountKey)
  19. if err != nil {
  20. log.Fatal("Erro ao realizar nova conexão com azure", err)
  21. return
  22. } else {
  23. fmt.Println("Sucesso ao se conectar com o azure")
  24. }
  25. u, err := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", accountName, containerName, blobName))
  26. if err != nil {
  27. c.JSON(http.StatusInternalServerError, gin.H{
  28. "Erro ao ler URL do container": err,
  29. })
  30. log.Fatal("Erro ao ler URL do container", err)
  31. return
  32. } else {
  33. fmt.Println("Sucesso ao ler URL do container, eu passei por aqui")
  34. c.JSON(200, gin.H{
  35. "Sucesso ao ler URL do container": "Eu passei por aqui",
  36. })
  37. }
  38. blobURL := azblob.NewBlockBlobURL(*u, azblob.NewPipeline(credential, azblob.PipelineOptions{}))
  39. c.JSON(200, gin.H{
  40. "Sucesso ao ler URL do container": "Próximo passo",
  41. })
  42. log.Println("Sucesso ao ler URL do container")
  43. form, err := c.MultipartForm()
  44. if err != nil {
  45. c.JSON(http.StatusInternalServerError, gin.H{
  46. "Erro ao ler arquivo": err.Error(),
  47. })
  48. log.Println("Erro ao ler arquivo", err)
  49. return
  50. }
  51. files := form.File["upload"]
  52. if len(files) == 0 {
  53. c.JSON(http.StatusBadRequest, gin.H{
  54. "Erro ao enviar arquivo para container": "Nenhum arquivo enviado",
  55. })
  56. log.Println("Nenhum arquivo enviado", err)
  57. return
  58. }
  59. file := files[0]
  60. fmt.Println("eu passei por files", file)
  61. log.Println(file.Filename)
  62. src, err := file.Open()
  63. if err != nil {
  64. c.JSON(500, gin.H{
  65. "Erro ao abrir arquivo": err,
  66. })
  67. log.Fatal("Erro ao abrir arquivo", err)
  68. return
  69. } else {
  70. fmt.Println("Sucesso ao abrir arquivo")
  71. c.JSON(200, gin.H{
  72. "Sucesso ao abrir arquivo": "Próximo passo",
  73. })
  74. }
  75. options := azblob.UploadStreamToBlockBlobOptions{
  76. MaxBuffers: 3,
  77. }
  78. _, err = azblob.UploadStreamToBlockBlob(context.Background(), src, blobURL, options)
  79. if err != nil {
  80. fmt.Println("deu erro, mas passei por aqui")
  81. c.JSON(http.StatusInternalServerError, "Deu erro, mas passei aqui")
  82. c.JSON(http.StatusInternalServerError, gin.H{
  83. "Erro ao enviar arquivo para container": err.Error(),
  84. })
  85. log.Println("Erro ao enviar arquivo para container", err)
  86. return
  87. } else {
  88. c.JSON(http.StatusOK, gin.H{
  89. "message": "Arquivo enviado com sucesso!",
  90. })
  91. fmt.Println("Sucesso ao enviar arquivo")
  92. }
  93. })
  94. router.Run(":8080")
  95. }

以下是使用Postman测试此API的步骤:

  1. 选择 POST 作为方法
  2. 输入API的URL
  3. body 标签下选择 form-data
  4. key 列中输入blob的名称,并选择类型为 file,然后选择文件
  5. 发送请求

我得到了以下错误:

  1. Erro ao enviar arquivo para container write error: -> github.com/Azure/azure-storage-blob-go/azblob.newStorageError, C:/Users/rodri/go/pkg/mod/github.com/!azure/azure-storage-blob-go@v0.15.0/azblob/zc_storage_error.go:42
  2. ===== RESPONSE ERROR (ServiceCode=InvalidUri) =====
  3. Description=The requested URI does not represent any resource on the server.
  4. RequestId:a31b34a1-401e-000c-3aa8-6fb698000000
  5. Time:2023-04-15T14:43:41.9699330Z, Details:
  6. Code: InvalidUri
  7. UriPath: https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==&comp=block&timeout=61
  8. PUT https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%3D&comp=block&timeout=61
  9. Authorization: REDACTED
  10. Content-Length: [5]
  11. User-Agent: [Azure-Storage/0.15 (go1.20; Windows_NT)]
  12. X-Ms-Client-Request-Id: [5e531a97-f854-476c-49f7-407a29468e89]
  13. X-Ms-Date: [Sat, 15 Apr 2023 14:43:41 GMT]
  14. X-Ms-Version: [2020-10-02]
  15. --------------------------------------------------------------------------------
  16. RESPONSE Status: 400 The requested URI does not represent any resource on the server.
  17. Content-Length: [438]
  18. Content-Type: [application/xml]
  19. Date: [Sat, 15 Apr 2023 14:43:41 GMT]
  20. Server: [Microsoft-HTTPAPI/2.0]
  21. X-Ms-Error-Code: [InvalidUri]
  22. X-Ms-Request-Id: [a31b34a1-401e-000c-3aa8-6fb698000000]

为什么会出现这个错误?

英文:

I'm building an API written in go and gin, which uploads blobs to Azure Storage. Here is the code:

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "net/url"
  8. "github.com/Azure/azure-storage-blob-go/azblob"
  9. "github.com/gin-gonic/gin"
  10. )
  11. func main() {
  12. router := gin.Default()
  13. router.POST("/upload", func(c *gin.Context) {
  14. accountName := "blablabla"
  15. accountKey := "mykey"
  16. containerName := "testblabla"
  17. blobName := c.PostForm("blobName")
  18. credential, err := azblob.NewSharedKeyCredential(accountName, accountKey)
  19. if err != nil {
  20. log.Fatal("Erro ao realizar nova conexão com azure", err)
  21. return
  22. } else {
  23. fmt.Println("Sucesso ao se conectar com o azure")
  24. }
  25. u, err := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", accountName, containerName, blobName))
  26. if err != nil {
  27. c.JSON(http.StatusInternalServerError, gin.H{
  28. "Erro ao ler URL do container": err,
  29. })
  30. log.Fatal("Erro ao ler URL do container", err)
  31. return
  32. } else {
  33. fmt.Println("Sucesso ao ler URL do container, eu passei por aqui")
  34. c.JSON(200, gin.H{
  35. "Sucesso ao ler URL do container": "Eu passei por aqui",
  36. })
  37. }
  38. blobURL := azblob.NewBlockBlobURL(*u, azblob.NewPipeline(credential, azblob.PipelineOptions{}))
  39. c.JSON(200, gin.H{
  40. "Sucesso ao ler URL do container": "Próximo passo",
  41. })
  42. log.Println("Sucesso ao ler URL do container")
  43. form, err := c.MultipartForm()
  44. if err != nil {
  45. c.JSON(http.StatusInternalServerError, gin.H{
  46. "Erro ao ler arquivo": err.Error(),
  47. })
  48. log.Println("Erro ao ler arquivo", err)
  49. return
  50. }
  51. files := form.File["upload"]
  52. if len(files) == 0 {
  53. c.JSON(http.StatusBadRequest, gin.H{
  54. "Erro ao enviar arquivo para container": "Nenhum arquivo enviado",
  55. })
  56. log.Println("Nenhum arquivo enviado", err)
  57. return
  58. }
  59. file := files[0]
  60. fmt.Println("eu passei por files", file)
  61. log.Println(file.Filename)
  62. src, err := file.Open()
  63. if err != nil {
  64. c.JSON(500, gin.H{
  65. "Erro ao abrir arquivo": err,
  66. })
  67. log.Fatal("Erro ao abrir arquivo", err)
  68. return
  69. } else {
  70. fmt.Println("Sucesso ao abrir arquivo")
  71. c.JSON(200, gin.H{
  72. "Sucesso ao abrir arquivo": "Proximo passo",
  73. })
  74. }
  75. options := azblob.UploadStreamToBlockBlobOptions{
  76. MaxBuffers: 3,
  77. }
  78. _, err = azblob.UploadStreamToBlockBlob(context.Background(), src, blobURL, options)
  79. if err != nil {
  80. fmt.Println("deu erro, mas passei por aqui")
  81. c.JSON(http.StatusInternalServerError, "Deu erro, mas passei aqui")
  82. c.JSON(http.StatusInternalServerError, gin.H{
  83. "Erro ao enviar arquivo para container": err.Error(),
  84. })
  85. log.Println("Erro ao enviar arquivo para container", err)
  86. return
  87. } else {
  88. c.JSON(http.StatusOK, gin.H{
  89. "message": "Arquivo enviado com sucesso!",
  90. })
  91. fmt.Println("Sucesso ao enviar arquivo")
  92. }
  93. })
  94. router.Run(":8080")
  95. }

Here are the steps to test this API with Postman:

  1. Select POST as the method
  2. Enter the URL of the API
  3. Select form-data under the body tab
  4. In the key column I put the name of the blob, and select the type file, then I select my file
  5. Send the request

I got this error:

  1. Erro ao enviar arquivo para container write error: -> github.com/Azure/azure-storage-blob-go/azblob.newStorageError, C:/Users/rodri/go/pkg/mod/github.com/!azure/azure-storage-blob-go@v0.15.0/azblob/zc_storage_error.go:42
  2. ===== RESPONSE ERROR (ServiceCode=InvalidUri) =====
  3. Description=The requested URI does not represent any resource on the server.
  4. RequestId:a31b34a1-401e-000c-3aa8-6fb698000000
  5. Time:2023-04-15T14:43:41.9699330Z, Details:
  6. Code: InvalidUri
  7. UriPath: https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==&comp=block&timeout=61
  8. PUT https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%3D&comp=block&timeout=61
  9. Authorization: REDACTED
  10. Content-Length: [5]
  11. User-Agent: [Azure-Storage/0.15 (go1.20; Windows_NT)]
  12. X-Ms-Client-Request-Id: [5e531a97-f854-476c-49f7-407a29468e89]
  13. X-Ms-Date: [Sat, 15 Apr 2023 14:43:41 GMT]
  14. X-Ms-Version: [2020-10-02]
  15. --------------------------------------------------------------------------------
  16. RESPONSE Status: 400 The requested URI does not represent any resource on the server.
  17. Content-Length: [438]
  18. Content-Type: [application/xml]
  19. Date: [Sat, 15 Apr 2023 14:43:41 GMT]
  20. Server: [Microsoft-HTTPAPI/2.0]
  21. X-Ms-Error-Code: [InvalidUri]
  22. X-Ms-Request-Id: [a31b34a1-401e-000c-3aa8-6fb698000000]

Why?

答案1

得分: 1

有什么问题吗?

请求中没有名为blobName的表单字段。

  1. blobName := c.PostForm("blobName")

证据

错误信息很明确:

  1. Code: InvalidUri
  2. UriPath: https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==&comp=block&timeout=61
  3. ^^^

  1. fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", accountName, containerName, blobName)
  2. ^^^

很明显blobName是空的。

解释

这个Postman请求

使用Go语言上传Azure的Blob。

作为原始的HTTP请求如下所示:

  1. POST /anything HTTP/1.1
  2. Host: httpbin.org
  3. Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryeobf4rJjB8V8AYfS
  4. ----WebKitFormBoundaryeobf4rJjB8V8AYfS
  5. Content-Disposition: form-data; name="upload"; filename="sample.pdf"
  6. <content omitted>
  7. ----WebKitFormBoundaryeobf4rJjB8V8AYfS
  8. Content-Disposition: form-data; name="blobName"
  9. myBlobName
  10. ----WebKitFormBoundaryeobf4rJjB8V8AYfS

如果你的处理程序处理这样的请求,

  • blobName := c.PostForm("blobName") 将是 myBlobName

  • files := form.File["upload"]; file := files[0] 获取描述上传文件的文件头

  • file.Filename 将是 sample.pdf

英文:

What's wrong?

There is not a form field named blobName in the request.

  1. blobName := c.PostForm(&quot;blobName&quot;)

Evidence

The error message is clear about this:

  1. Code: InvalidUri
  2. UriPath: https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==&amp;comp=block&amp;timeout=61
  3. ^^^

Comparing to

  1. fmt.Sprintf(&quot;https://%s.blob.core.windows.net/%s/%s&quot;, accountName, containerName, blobName)
  2. ^^^

It's obviously that blobName is empty.

Explanation

This Postman request

使用Go语言上传Azure的Blob。

looks like this as a raw HTTP request:

  1. POST /anything HTTP/1.1
  2. Host: httpbin.org
  3. Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryeobf4rJjB8V8AYfS
  4. ----WebKitFormBoundaryeobf4rJjB8V8AYfS
  5. Content-Disposition: form-data; name=&quot;upload&quot;; filename=&quot;sample.pdf&quot;
  6. &lt;content omitted&gt;
  7. ----WebKitFormBoundaryeobf4rJjB8V8AYfS
  8. Content-Disposition: form-data; name=&quot;blobName&quot;
  9. myBlobName
  10. ----WebKitFormBoundaryeobf4rJjB8V8AYfS

If such a request is handled by your handler,

  • blobName := c.PostForm(&quot;blobName&quot;) will be myBlobName

  • files := form.File[&quot;upload&quot;]; file := files[0] gets the file header describing the uploaded file

  • file.Filename will be sample.pdf

huangapple
  • 本文由 发表于 2023年4月15日 22:53:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76023001.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定