Django从Azure存储返回二进制大对象(blob),作为可下载文件

5
我是新手,正在使用azure-storage和django。我的开发环境软件配置如下:django 1.10,python 2.7.6,azure-storage-blob 0.37。我正在使用django应用程序作为Web服务API,前端使用angular-2和HTML构建。
我正在使用azure blob存储来存储任何类型的文件。
我保存文件的Azure Blob容器只有私有访问权限。我能够成功上传文件。
问题在于下载文件时:
我想要实现的是:
1.当有人点击页面上的超链接时,请求将转到django视图,并携带blob名称。然后我可以使用容器名称和blob名称获取blob。 block_blob_service._get_blob(container,blob_name)
2.我想要将该blob作为可下载文件返回给django响应。
您能否提供解决方案或更好的方法来实现此目标?
谢谢。
2个回答

8

我建议你在Django中使用Azure存储系统

请按照这个教程来配置你的Azure存储账户到你的项目中。

# Replace <...> appropriately with your information

# AzureStorage Settings
AZURE_STORAGE_ACCOUNT = "<account_name>"
AZURE_STORAGE_KEY = "<account_key>"
AZURE_STORAGE_CONTAINER = "<default_storage_container>" # statics will use this container

# Static Settings
STATICFILES_STORAGE = "<my_project>.storage.AzureStorage"
STATIC_URL = "http://<storage account>.blob.core.windows.net/<default_storage_container>/"

# Media Settings
MEDIA_URL = 'http://storage.pepperdeck.com/<media_container>/'

您可以在这里这里获得更多详细信息。

更新回答: 实际上,我昨天提供的Django-Azure-Storage本质上是azure存储SDK的一个适配器调用。你在回复中提到的媒体容器实际上不需要配置,因为你只涉及到azure存储。

根据您的需求,只需使用Azure存储Python SDK。

请按照以下步骤进行操作。

步骤1:将您想要下载的blob名称绑定到您的超链接中,并在用户单击时将blob名称作为参数传递给后端。

步骤2:获取Blob URL。

def GetBlobUrl():
    blobService = BlockBlobService(account_name=accountName, account_key=accountKey)
    sas_token = blobService.generate_container_shared_access_signature(containerName,ContainerPermissions.READ, datetime.utcnow() + timedelta(hours=1))
    # print url
    return 'https://' + <your_account_name> + '.blob.core.windows.net/' + <your_container_name> + '/<your_blob_name>?' + sas_token

步骤3:通过StreamingHttpResponse在浏览器中下载文件。

import requests
from django.http import StreamingHttpResponse

def stream_file(request, *args, **kwargs):
    file_url = "<blob url you get in the Previous step >"

    r = requests.get(file_url, stream=True)

    resp = StreamingHttpResponse(streaming_content=r)
    resp['Content-Disposition'] = 'attachment; filename="<your blob name>"'

您还可以参考以下主题:

1.将远程URL的文件流式传输到Django视图响应

2.如何在Django中向客户端流式传输文件

希望对您有所帮助。


你能详细说明一下MEDIA_URL和MEDIA_ROOT是什么,以及urls.py需要哪些设置吗? - sachin27
@sachin27 当然可以。请给我一些时间来更新我的答案。 - Jay Gong
@sachin27 你好,请查看我的更新答案。如有任何疑问,请随时告诉我。 - Jay Gong
1
@sachin27 我尝试搜索了很多文档,但是没有找到关于私有访问和匿名访问性能的官方描述。根据我的经验,这两种访问方式都是REST API,而私有访问应该是推荐的,因为它更加安全。 - Jay Gong
在上述情况下,流媒体URL将在临时期间处于活动状态。如果我必须存储已上传视频的链接以便下次访问,最好的方法是什么?提前致谢。 - sachin27
显示剩余4条评论

0

我可以为@Jay Gong的答案添砖加瓦。

第一个答案

这是针对azure-storage-blob v12的解决方案。

azure-storage-blob==12.8.1

import requests

from django.http import StreamingHttpResponse

from app_module.settings import AZURE_ACCOUNT_KEY # blob storage access key
from app_module.settings import AZURE_ACCOUNT_NAME # blob storage name
from app_module.settings import AZURE_CONTAINER # name of container
from app_module.settings import AZURE_ENDPOINT_SUFFIX # "core.windows.net"


def get_blob_url(file_path):
    sas_token = generate_account_sas(
        account_name=AZURE_ACCOUNT_NAME,
        account_key=AZURE_ACCOUNT_KEY,
        resource_types=ResourceTypes(service=True, container=True, object=True),
        permission=AccountSasPermissions(read=True),
        expiry=datetime.utcnow() + timedelta(hours=1)
    )

    return f'https://{AZURE_ACCOUNT_NAME}.blob.{AZURE_ENDPOINT_SUFFIX}/{AZURE_CONTAINER}/{file_path}?{sas_token}'


def download(request):
    file_name = 'example.png'
    file_location_in_blob = '/path/to/file/inside/blob/storage/' + file_name

    url = get_blob_url(file_location_in_blob)

    request = requests.get(url, stream=True)
    response = StreamingHttpResponse(streaming_content=request)

    response['Content-Disposition'] = f'attachment; filename={file_name}'

    return response

第二个答案

这是针对azure-storage-blob v2的解决方案。它更加优雅,因为您不必构建流式响应。

azure-storage-blob==2.1.0 

from django.http import HttpResponse

def download(request):
    object = Model.objects.last()
    
    # file is FileField or its deriveritives ImageField
    response = HttpResponse(object.file) 
    response['Content-Disposition'] = f'attachment; filename={file_name}'

    return response

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接