我已经使用HTTP触发器在Azure上创建了Cloud Function,并且希望能够使用表单处理文件上传。
我的入口点看起来像这样:
def main(req: func.HttpRequest) -> func.HttpResponse:
body = req.get_body()
headers=req.headers
...
问题是我在body
中得到的是原始二进制文件,我不知道如何解码它并获取上载的文件。
有人知道实现这一目标的好方法吗?
答案 0 :(得分:2)
我想说,这是一种Azure本机方法,而Python本机。
azure.functions.HttpRequest
具有一个files
生成器的MultiDict
属性。使用方法如下:
import logging
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
for input_file in req.files.values():
filename = input_file.filename
contents = input_file.stream.read()
logging.info('Filename: %s' % filename)
logging.info('Contents:')
logging.info(contents)
[..process the file here as you want..]
return func.HttpResponse(f'Done\n')
如果您只想使用标准的Python库(例如,为了提高可移植性),那么您应该知道您需要在体内解析的是二进制形式的MIME multipart message:>
Content-Type: multipart/form-data; boundary=--------------------------1715cbf149d89cd9
--------------------------1715cbf149d89cd9
Content-Disposition: form-data; name="data"; filename="test.txt"
Content-Type: application/octet-stream
this is a test document
--------------------------1715cbf149d89cd9--
要复制的示例脚本:
echo 'this is a test document' > test.txt && curl -F 'data=@test.txt' 'https://[..yourfunctionname..].azurewebsites.net/api/HttpTrigger'
您会感到惊讶,但是email
模块would do it为您服务(我个人认为它的名字不好用)。
下面的示例代码(注意:没有错误处理!)突出了核心思想:
import cgi
import email
import logging
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
# Content-Type should be 'multipart/form-data' with some boundary
content_type = req.headers.get('Content-Type')
body = req.get_body().decode('utf-8')
mime_template = 'MIME-Version: 1.0\nContent-Type: %s\n%s'
post_data = email.parser.Parser().parsestr(mime_template % (content_type, body))
# Content-Disposition header format:
# 'form-data; name="data"; filename="test.txt"'
disposition = post_data.get_payload()[0]['Content-Disposition']
disposition_value = cgi.parse_header('Content-Disposition: %s' % disposition)[1]
filename = disposition_value['filename']
contents = post_data.get_payload()[0].get_payload()
logging.info('Filename: %s' % filename)
logging.info('Contents:')
logging.info(contents)
[..process the file here as you want..]
return func.HttpResponse(f'Done\n')
答案 1 :(得分:1)
我认为最好的解决方法是将这些二进制数据转换为文件,然后上传到blob存储,
#upload to picture to blob storage
block_blob_service = BlockBlobService(account_name=accuntName, account_key=accuntKey)
container_name = 'machineimages'
blob_name = image_name + '.jpeg'
# Creating the blob
block_blob_service.create_blob_from_bytes(container_name, blob_name, decoded_image,
content_settings=ContentSettings(content_type='image/png'))
logging.info("Successfull blob creating ")
# Returning a succesful post request
return func.HttpResponse(f"successful request")
这里是 sample
。
答案 2 :(得分:0)
显然,我们默认获取的最新python SDK [1]中既没有 create_blob_from_bytes 也没有 BlobServiceClient 。
所以我不得不绕道而行。
from azure.storage.blob import (
BlobServiceClient,
ContentSettings
)
# decoding base64 image from json body
decoded_image = base64.b64decode(image)
blob_service_client = BlobServiceClient.from_connection_string(
conn_str=storage_connection_string
)
logging.debug(f'getting client for container : {container_name}')
container_client =
blob_service_client.get_container_client(container=container_name)
blob_client = container_client.get_blob_client(blob_name)
if blob_client.exists():
blob_client.delete_blob()
blob_client = blob_service_client.get_blob_client(container=container_name,
blob=blob_name)
try:
blob_client.upload_blob(decoded_image)
content_settings =ContentSettings(content_type='image/png')
logging.debug(f'setting the content type : {content_settings}')
except Exception as e:
logging.error(str(e))