英文:
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的步骤:
- 选择 POST 作为方法
- 输入API的URL
- 在 body 标签下选择 form-data
- 在 key 列中输入blob的名称,并选择类型为 file,然后选择文件
- 发送请求
我得到了以下错误:
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:
- Select POST as the method
- Enter the URL of the API
- Select form-data under the body tab
- In the key column I put the name of the blob, and select the type file, then I select my file
- 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请求
作为原始的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("blobName")
Evidence
The error message is clear about this:
Code: InvalidUri
UriPath: https://blablabla.blob.core.windows.net/teste/?blockid=mLa1s8Y9Tu6Tqw0umZ2kiwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==&comp=block&timeout=61
^^^
Comparing to
fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", accountName, containerName, blobName)
^^^
It's obviously that blobName
is empty.
Explanation
This Postman request
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="upload"; filename="sample.pdf"
<content omitted>
----WebKitFormBoundaryeobf4rJjB8V8AYfS
Content-Disposition: form-data; name="blobName"
myBlobName
----WebKitFormBoundaryeobf4rJjB8V8AYfS
If such a request is handled by your handler,
-
blobName := c.PostForm("blobName")
will bemyBlobName
-
files := form.File["upload"]; file := files[0]
gets the file header describing the uploaded file -
file.Filename
will besample.pdf
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论