使用Go语言上传Azure的Blob。

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

upload blobs with go - azure

问题

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

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/Azure/azure-storage-blob-go/azblob"
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()

	router.POST("/upload", func(c *gin.Context) {
		accountName := "blablabla"
		accountKey := "mykey"
		containerName := "testblabla"
		blobName := c.PostForm("blobName")

		credential, err := azblob.NewSharedKeyCredential(accountName, accountKey)
		if err != nil {
			log.Fatal("Erro ao realizar nova conexão com azure", err)
			return
		} else {
			fmt.Println("Sucesso ao se conectar com o azure")
		}

		u, err := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", accountName, containerName, blobName))
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"Erro ao ler URL do container": err,
			})
			log.Fatal("Erro ao ler URL do container", err)
			return
		} else {
			fmt.Println("Sucesso ao ler URL do container, eu passei por aqui")
			c.JSON(200, gin.H{
				"Sucesso ao ler URL do container": "Eu passei por aqui",
			})
		}
		blobURL := azblob.NewBlockBlobURL(*u, azblob.NewPipeline(credential, azblob.PipelineOptions{}))
		c.JSON(200, gin.H{
			"Sucesso ao ler URL do container": "Próximo passo",
		})
		log.Println("Sucesso ao ler URL do container")

		form, err := c.MultipartForm()
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"Erro ao ler arquivo": err.Error(),
			})
			log.Println("Erro ao ler arquivo", err)
			return
		}

		files := form.File["upload"]
		if len(files) == 0 {
			c.JSON(http.StatusBadRequest, gin.H{
				"Erro ao enviar arquivo para container": "Nenhum arquivo enviado",
			})
			log.Println("Nenhum arquivo enviado", err)
			return
		}

		file := files[0]

		fmt.Println("eu passei por files", file)

		log.Println(file.Filename)

		src, err := file.Open()
		if err != nil {
			c.JSON(500, gin.H{
				"Erro ao abrir arquivo": err,
			})
			log.Fatal("Erro ao abrir arquivo", err)
			return
		} else {
			fmt.Println("Sucesso ao abrir arquivo")
			c.JSON(200, gin.H{
				"Sucesso ao abrir arquivo": "Próximo passo",
			})
		}

		options := azblob.UploadStreamToBlockBlobOptions{
			MaxBuffers: 3,
		}
		_, err = azblob.UploadStreamToBlockBlob(context.Background(), src, blobURL, options)

		if err != nil {
			fmt.Println("deu erro, mas passei por aqui")
			c.JSON(http.StatusInternalServerError, "Deu erro, mas passei aqui")
			c.JSON(http.StatusInternalServerError, gin.H{
				"Erro ao enviar arquivo para container": err.Error(),
			})
			log.Println("Erro ao enviar arquivo para container", err)
			return
		} else {
			c.JSON(http.StatusOK, gin.H{
				"message": "Arquivo enviado com sucesso!",
			})
			fmt.Println("Sucesso ao enviar arquivo")

		}
	})
	router.Run(":8080")
}

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

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

我得到了以下错误:

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
===== RESPONSE ERROR (ServiceCode=InvalidUri) =====
Description=The requested URI does not represent any resource on the server.
RequestId:a31b34a1-401e-000c-3aa8-6fb698000000
Time:2023-04-15T14:43:41.9699330Z, Details:
Code: InvalidUri
UriPath: https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==&comp=block&timeout=61        
PUT https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%3D&comp=block&timeout=61
Authorization: REDACTED
Content-Length: [5]
User-Agent: [Azure-Storage/0.15 (go1.20; Windows_NT)]
X-Ms-Client-Request-Id: [5e531a97-f854-476c-49f7-407a29468e89]
X-Ms-Date: [Sat, 15 Apr 2023 14:43:41 GMT]
X-Ms-Version: [2020-10-02]
--------------------------------------------------------------------------------
RESPONSE Status: 400 The requested URI does not represent any resource on the server.      
Content-Length: [438]
Content-Type: [application/xml]
Date: [Sat, 15 Apr 2023 14:43:41 GMT]
Server: [Microsoft-HTTPAPI/2.0]
X-Ms-Error-Code: [InvalidUri]
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:

package main
import (
"context"
"fmt"
"log"
"net/http"
"net/url"
"github.com/Azure/azure-storage-blob-go/azblob"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.POST("/upload", func(c *gin.Context) {
accountName := "blablabla"
accountKey := "mykey"
containerName := "testblabla"
blobName := c.PostForm("blobName")
credential, err := azblob.NewSharedKeyCredential(accountName, accountKey)
if err != nil {
log.Fatal("Erro ao realizar nova conexão com azure", err)
return
} else {
fmt.Println("Sucesso ao se conectar com o azure")
}
u, err := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", accountName, containerName, blobName))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"Erro ao ler URL do container": err,
})
log.Fatal("Erro ao ler URL do container", err)
return
} else {
fmt.Println("Sucesso ao ler URL do container, eu passei por aqui")
c.JSON(200, gin.H{
"Sucesso ao ler URL do container": "Eu passei por aqui",
})
}
blobURL := azblob.NewBlockBlobURL(*u, azblob.NewPipeline(credential, azblob.PipelineOptions{}))
c.JSON(200, gin.H{
"Sucesso ao ler URL do container": "Próximo passo",
})
log.Println("Sucesso ao ler URL do container")
form, err := c.MultipartForm()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"Erro ao ler arquivo": err.Error(),
})
log.Println("Erro ao ler arquivo", err)
return
}
files := form.File["upload"]
if len(files) == 0 {
c.JSON(http.StatusBadRequest, gin.H{
"Erro ao enviar arquivo para container": "Nenhum arquivo enviado",
})
log.Println("Nenhum arquivo enviado", err)
return
}
file := files[0]
fmt.Println("eu passei por files", file)
log.Println(file.Filename)
src, err := file.Open()
if err != nil {
c.JSON(500, gin.H{
"Erro ao abrir arquivo": err,
})
log.Fatal("Erro ao abrir arquivo", err)
return
} else {
fmt.Println("Sucesso ao abrir arquivo")
c.JSON(200, gin.H{
"Sucesso ao abrir arquivo": "Proximo passo",
})
}
options := azblob.UploadStreamToBlockBlobOptions{
MaxBuffers: 3,
}
_, err = azblob.UploadStreamToBlockBlob(context.Background(), src, blobURL, options)
if err != nil {
fmt.Println("deu erro, mas passei por aqui")
c.JSON(http.StatusInternalServerError, "Deu erro, mas passei aqui")
c.JSON(http.StatusInternalServerError, gin.H{
"Erro ao enviar arquivo para container": err.Error(),
})
log.Println("Erro ao enviar arquivo para container", err)
return
} else {
c.JSON(http.StatusOK, gin.H{
"message": "Arquivo enviado com sucesso!",
})
fmt.Println("Sucesso ao enviar arquivo")
}
})
router.Run(":8080")
}

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:

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
===== RESPONSE ERROR (ServiceCode=InvalidUri) =====
Description=The requested URI does not represent any resource on the server.
RequestId:a31b34a1-401e-000c-3aa8-6fb698000000
Time:2023-04-15T14:43:41.9699330Z, Details:
Code: InvalidUri
UriPath: https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==&comp=block&timeout=61        
PUT https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%3D&comp=block&timeout=61
Authorization: REDACTED
Content-Length: [5]
User-Agent: [Azure-Storage/0.15 (go1.20; Windows_NT)]
X-Ms-Client-Request-Id: [5e531a97-f854-476c-49f7-407a29468e89]
X-Ms-Date: [Sat, 15 Apr 2023 14:43:41 GMT]
X-Ms-Version: [2020-10-02]
--------------------------------------------------------------------------------
RESPONSE Status: 400 The requested URI does not represent any resource on the server.      
Content-Length: [438]
Content-Type: [application/xml]
Date: [Sat, 15 Apr 2023 14:43:41 GMT]
Server: [Microsoft-HTTPAPI/2.0]
X-Ms-Error-Code: [InvalidUri]
X-Ms-Request-Id: [a31b34a1-401e-000c-3aa8-6fb698000000]

Why?

答案1

得分: 1

有什么问题吗?

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

blobName := c.PostForm("blobName")

证据

错误信息很明确:

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

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

很明显blobName是空的。

解释

这个Postman请求

使用Go语言上传Azure的Blob。

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

POST /anything HTTP/1.1
Host: httpbin.org
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryeobf4rJjB8V8AYfS
 
----WebKitFormBoundaryeobf4rJjB8V8AYfS
Content-Disposition: form-data; name="upload"; filename="sample.pdf"

<content omitted>
----WebKitFormBoundaryeobf4rJjB8V8AYfS
Content-Disposition: form-data; name="blobName"
myBlobName
----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.

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

Evidence

The error message is clear about this:

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

Comparing to

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

It's obviously that blobName is empty.

Explanation

This Postman request

使用Go语言上传Azure的Blob。

looks like this as a raw HTTP request:

POST /anything HTTP/1.1
Host: httpbin.org
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryeobf4rJjB8V8AYfS
----WebKitFormBoundaryeobf4rJjB8V8AYfS
Content-Disposition: form-data; name=&quot;upload&quot;; filename=&quot;sample.pdf&quot;
&lt;content omitted&gt;
----WebKitFormBoundaryeobf4rJjB8V8AYfS
Content-Disposition: form-data; name=&quot;blobName&quot;
myBlobName
----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:

确定