【问题标题】:protecting user uploaded files django保护用户上传的文件 django
【发布时间】:2012-02-26 15:25:42
【问题描述】:

如何允许用户将文件上传到他们自己的、用户指定的文件夹,并且只能看到他们上传的文件?我正在使用 django 文件传输。目前它让我可以选择将媒体放入哪个文件,但我可以将其放入任何用户的文件并查看每个用户的媒体。这是我的上传/models.py:

from django.db import models
from django.contrib.auth.models import User, UserManager

def uploadmodel_file_upload_to(instance, filename):
    print 'instance.user.username = '+ str(instance.user.username)
    return 'uploads/%s/%s' % (instance.user.username, filename)

class UploadModel(models.Model):
    user = models.ForeignKey('auth.user')
    file = models.FileField(upload_to=uploadmodel_file_upload_to)

【问题讨论】:

  • “目前它给了我一个选择”? “它”?什么给了你选择?
  • “它”是用户。在表单上,​​它为我提供了一个下拉表单,其中包含所有用户可供选择。
  • “在表单上它给了我一个下拉表单”?真的吗?这是否意味着您正在为此模型使用默认的 ModelForm?如果是这样,请更新问题以显示这一点。和。正在执行什么视图功能?这是默认的管理员视图吗?或者你写的视图函数?请更新问题以提供所有信息。请不要添加 cmets。

标签: python django


【解决方案1】:

uploadmodel_file_upload_to 返回一个相对路径。要构建完整路径,django 会预先设置 settings.MEDIA_ROOT。 MEDIA_ROOT 应该是公开可读的。

所以我们想将文件保存在 MEDIA_ROOT 之外。在 settings.py 中添加类似这样的内容:

import os.path
PROJECT_ROOT=os.path.abspath(os.path.dirname(__file__))
PROTECTED_MEDIA_ROOT=os.path.join(PROJECT_ROOT, 'protected_uploads')

现在您可以更新 uploadmodel_file_upload_to 以返回绝对路径:

def uploadmodel_file_upload_to(instance, filename):
    return '%s/%s/%s' % (settings.PROTECTED_MEDIA_ROOT, instance.user.username,
        filename)

现在文件保存在 /project/path/protected_uploads 中,我们需要添加一个视图来服务它,例如:

import os 
import mimetypes

from django import shortcuts
from django import http
from django.conf import settings
from django.views.static import was_modified_since
from django.utils.http import http_date

from .models import *

def serve_upload(request, upload_id):
    upload = shortcuts.get_object_or_404(UploadModel, pk=upload_id)
    fullpath = upload.file.path

    if request.user != upload.user:
        return http.HttpResponseForbidden()

    statobj = os.stat(fullpath)
    mimetype, encoding = mimetypes.guess_type(fullpath)
    mimetype = mimetype or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj.st_mtime, statobj.st_size):
        return http.HttpResponseNotModified(mimetype=mimetype)
    response = http.HttpResponse(open(fullpath, 'rb').read(), mimetype=mimetype)
    response["Last-Modified"] = http_date(statobj.st_mtime)
    response["Content-Length"] = statobj.st_size
    if encoding:
        response["Content-Encoding"] = encoding
    return response

还有一个网址:

url(r'serve_upload/(?P<upload_id>\d+)/$', 'serve_upload'),

【讨论】:

  • 如果您使用缓存,如果您不想内存不足,最好不要缓存 serve_upload 调用。从 django.views.decorators.cache 导入 never_cache @never_cache def serve_upload...
  • 谢谢@jpic,以上所有sn-ps都运行良好,需要进行一次编辑,即在response = http.HttpResponse(open(fullpath, 'rb').read(), content_type=mimetype)行中参考link
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 2012-06-14
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多