coding tips

django REST framework downloading binary files

When returning a Response from django REST API that contains a binary file, you may encounter an issue:

UnicodeDecodeError: ‘utf-8’ codec can’t decode byte  in position 11: invalid start byte

That’s because the renderer tries to decode it as text, despite content-type suggesting otherwise. To achieve the desired you need to write your own renderer.

from rest_framework.renderers import BaseRenderer

class BinaryRenderer(BaseRenderer):
    media_type = 'application/*'
    format = 'binary'
    charset = None
    render_style = 'binary'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data

and then apply it to the desired API function. If you use @api_view decorator add  @renderer_classes=((BinaryRenderer, )) .

If you use APIView or any of the ViewSets, you can set permissions for all methods in view, by assigning them to  renderer_classes variable, or for just one, by re-implementing a def get_rendererss(self)  method [1] (the example shows permissions, but it’s the same principle with renderers).

Third option is when you use  the @action decorator (or @list_route and @detail_route. Then you can simply add another parameter renderer_classesto it.