5

I am new to azure-storage and django My dev environment software configuration is as- django 1.10 , python 2.7.6, azure-storage-blob 0.37. I am using django application as webservice api and frontend is built using angular-2 and HTML

I am using azure blob storage for storing files with any type.

azure blob Container where which I am saving files have private access only.I am able to upload file successfully.

The problem is while downloading file- what I am trying to achieve is-

  1. When someone clicks on hyperlink on page request will go to django view with blob name. then I can get blob using container name and blob name

    block_blob_service._get_blob(container,blob_name)

  2. I want to return that blob as downloadable file in django response.

Can you suggest be solution or better approach where I can achieve this.

Thanks in advance.

sachin27
  • 145
  • 3
  • 13

2 Answers2

8

I suggest you using Azure Storage System in Django.

Please follow this tutorial to configure your azure storage account in your project.

# 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>/'

You could get more details here and here.


Update Answer: Actually,The Django-Azure-Storage I provided yesterday is essentially a adapter call for azure storage SDK . The media container you mentioned in your reply is actually don't need to be configured , because you only refer to azure storage.

According to you needs , just use Azure Storage Python SDK.

Please follow the steps below.

Step1: Bind the name of your blob which you want to download to your hyperlink, and pass the blob name as a parameter to the backend when the user clicks.

Step2: Get 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

Step3: Download a file in a browser via 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>"'

You could also refer to the threads below:

1.Stream file from remote url to Django view response

2.how to stream file to client in django

Hope it helps you.

Jay Gong
  • 23,163
  • 2
  • 27
  • 32
  • MEDIA_URL = 'http://storage.pepperdeck.com//' in this what media_conatiner? – sachin27 Oct 11 '17 at 09:37
  • can you give some details about what will be MEDIA_URL and MEDIA_ROOT and what are settings required urls.py – sachin27 Oct 12 '17 at 05:03
  • @sachin27 Sure.Please give me some time to update my answer. – Jay Gong Oct 12 '17 at 05:13
  • @sachin27 Hi,please see my update answer.Any concern,please feel free to let me know. – Jay Gong Oct 12 '17 at 09:33
  • Thanks. It is working for me. I have one query, if I use azure container with private access for profile images, how much this affect in performance compare to azure container with anonymous access. – sachin27 Oct 12 '17 at 12:57
  • 1
    @sachin27 I tried to search for lots of documents, but I didn't find an official description about performance of private access and anonymous access. Per my experience, the two ways of access are all REST API and private access should be recommended because it's security. – Jay Gong Oct 13 '17 at 02:43
  • Thank you very much for your help. – sachin27 Oct 13 '17 at 04:41
  • In above case streaming url will be active for temporary period. What is the best approach if I have to store link of uploaded video so that I can access it next time? Thanks in advance. – sachin27 Oct 27 '17 at 06:44
  • `BlockBlobService` class is deprecated since **v12 SDK** you might use `BlobServiceClient` instead (`from azure.storage.blob import BlobServiceClient`). – Lukasz Dynowski Jul 21 '21 at 11:25
0

I can add my few cents to @Jay Gong answer.

1st Answer

This is solution for 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

2nd Answer

This is solution for azure-storage-blob v2. It's more elegant since you don't have to build streaming response.

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
Lukasz Dynowski
  • 11,169
  • 9
  • 81
  • 124