通过Django-Filer而不是重定向下载文件

时间:2018-11-29 20:51:01

标签: python django django-models django-views

我正在制作一个文件服务系统,该系统可以根据类别组织不同的文件。用户找到所需文件后,单击下载按钮,然后将其下载。这些文件具有各种不同的pdf,ai,video等类型。我在HTML上使用了download属性,并且可以在本地找到它,但是当我将其推送到托管服务时,我发现它不起作用。

我已经阅读了20篇有关使用Content-Dispostion的文章,但是我甚至遇到了麻烦。我没有什么可做的,但是下面是我尝试访问文件以将其推回用户的尝试。老实说,我只是不确定从这里出发。我只希望用户能够单击一个按钮,然后下载django-filer文件

让我知道是否需要添加其他任何内容。

def asset_detail_view(request, slug, *args, **kwargs):
    obj = get_object_or_404(Asset.objects.prefetch_related('file_set'), slug=slug)

    context = {
        'object': obj,
    }
    return render(request, 'detail_view.html', context)

def search(request):
    queryset = Asset.objects.prefetch_related('file_set').all()
    filter_set = AssetFilter(request.GET, queryset=queryset)
    return render(request, 'asset_filter_view.html', {'filter': filter_set})

def download(request, slug):
    download = File.objects.filter( asset__slug=slug ).first()
    file = FilerFile.objects.filter(id=download.file_id)
    for attr, value in file.__dict__.items():
        print(attr, value)


    return HttpResponse("Test")

模型

class Asset(models.Model):
    name = models.CharField(max_length=50, blank=False)
    slug = models.SlugField()
    summary = models.TextField(max_length=120, blank=True, default='Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sapiente esse necessitatibus neque sequi doloribus.')
    asset_type = models.ForeignKey(File_Type, blank=False)
    description = PlaceholderField('asset_description')
    asset_category = models.ManyToManyField(Asset_Category, blank=True)
    tag = models.ManyToManyField(Tag, blank=True)
    product_category = models.ManyToManyField(Category, blank=True)
    product_series = models.ManyToManyField(Series, blank=True)
    product_line = models.ManyToManyField(Line, blank=True)
    product = models.ManyToManyField(Product, blank=True)
    url = models.CharField(max_length=250, blank=True, verbose_name='Video URL')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_active = models.BooleanField(default=True)


    def get_absolute_url(self):
        return reverse("assets:asset_detail", kwargs={"slug": self.slug})

    def __str__(self):
        return self.name

class File(models.Model):
    name = models.CharField(max_length=50, blank=False)
    description = models.TextField(blank=True)
    image = FilerImageField(default=28, null=True, blank=True, related_name="image_file", verbose_name="Thumbnail")
    file = FilerFileField(null=True, blank=True, related_name="file_file")
    asset = models.ForeignKey(Asset, blank=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_active = models.BooleanField(default=True)

    def __str__(self):
        return self.name

1 个答案:

答案 0 :(得分:0)

要回答我自己的问题。我不确定这是否是最好的方法,但是它对我有用。 我没有在资产_detail_view内创建条件语句来捕获通过模板提交的表单,而不是创建用于下载图像的新URL。我认为这是大多数其他答案的做法,但是(我认为)它没有得到很好的解释,所以我很困惑其他人放置此逻辑的地方。这确实在本地中断了该过程,因为它必须打开一个URL,而urllib不知道如何处理本地路径。

HTML模板:

<div>
      <form>
            <input type="text" name="path" value="{{ **object url** }}" hidden>
            <input class="btn btn-primary" type="submit" value="Download">
      </form>
</div>

在这里,您将需要找到一种获取文件URL的方法,我使用的是django-filer,所以很简单。我删除了为获得它而必须做的其他调用,因为它是我的代码自定义的,对其他人不起作用。提交后,将其发送到已经存在的视图中,但是现在附加了变量path

views.py

from urllib.request import Request, urlopen

def asset_detail_view(request, slug, *args, **kwargs):
    obj = get_object_or_404(Asset.objects.prefetch_related('file_set'), slug=slug)

    context = {
        'object': obj,
    }

    if request.GET:
        query = request.GET
        filepath = query.get('path','0')
        filename = os.path.basename(os.path.normpath(filepath))
        hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
       'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
       'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
       'Accept-Encoding': 'none',
       'Accept-Language': 'en-US,en;q=0.8',
       'Connection': 'keep-alive'}

        req = Request(filepath, headers=hdr)

        with urlopen(req) as f:
            response = HttpResponse(f.read(), content_type='application/octet-stream')
            response['Content-Type'] = 'application/octet-stream'
            response['Content-Disposition'] = 'attachment; filename={0}'.format(filename)
            print (response['Content-Disposition'])
            return response


    return render(request, 'detail_view.html', context)

hdr变量对我来说很奇怪,我不得不做一些挖掘才能找到它。据我了解,您实际上是在说服服务器您是浏览器,而不是试图访问服务器的代码块。您可以复制并粘贴。

如果有任何其他人要添加任何东西,或者有更简单的方法来处理此问题,请随时发表评论或回答。希望这对其他人有帮助!