2010-02-16 4 views
8

Je souhaite stocker les fichiers téléchargés dans un répertoire spécifique qui dépend de l'URI de la requête POST. Peut-être, je voudrais aussi renommer le fichier à quelque chose de fixe (le nom de l'entrée du fichier par exemple) donc j'ai un moyen facile de grep le système de fichiers, etc. et aussi pour éviter d'éventuels problèmes de sécurité.Django télécharge le fichier dans un répertoire spécifique dépendant de l'URI POST

Quelle est la meilleure façon de le faire dans Django?

Edit: Je dois préciser que je serais intéressé à faire peut-être cela comme un gestionnaire de téléchargement de fichiers pour éviter d'écrire un fichier volumineux à deux reprises pour le système de fichiers.

Edit2: Je suppose que l'on peut juste « mv » le fichier tmp vers un nouvel emplacement. C'est une opération bon marché si sur le même système de fichiers.

+0

le déplacement du fichier temporaire est ok.Django vérifie ce cas et ne se plaint pas s'il disparaît: http://code.djangoproject.com/browser/django/trunk/django/core/files/uploadedfile.py#L57 – olooney

Répondre

3

Django vous donne un contrôle total sur l'endroit où (et si) vous enregistrez des fichiers. Voir: http://docs.djangoproject.com/en/dev/topics/http/file-uploads/

L'exemple ci-dessous montre comment combiner l'URL et le nom du fichier téléchargé et écrire le fichier sur le disque:

def upload(request): 
    folder = request.path.replace("/", "_") 
    uploaded_filename = request.FILES['file'].name 

    # create the folder if it doesn't exist. 
    try: 
     os.mkdir(os.path.join(BASE_PATH, folder)) 
    except: 
     pass 

    # save the uploaded file inside that folder. 
    full_filename = os.path.join(BASE_PATH, folder, uploaded_filename) 
    fout = open(full_filename, 'wb+') 
    # Iterate through the chunks. 
    for chunk in fout.chunks(): 
     fout.write(chunk) 
    fout.close() 

Edit: Comment faire cela avec un FileUploadHandler? Il remonte à travers le code et il semble que vous devez faire quatre choses pour reformater le TemporaryFileUploadHandler pour sauver l'extérieur de FILE_UPLOAD_TEMP_DIR:

  1. étendre TemporaryUploadedFile et passer outre initialisation() pour passer à travers un répertoire différent de NamedTemporaryFile . Il peut utiliser le try mkdir sauf pour le passage que j'ai montré ci-dessus.

  2. étendez TemporaryFileUploadHandler et remplacez new_file() pour utiliser la classe ci-dessus.

  3. également étendre init() pour accepter le répertoire dans lequel vous souhaitez que le dossier à aller.

  4. ajouter le gestionnaire Dynamiquement de demande, en passant par un répertoire déterminé à partir de l'URL:

    request.upload_handlers = [ProgressBarUploadHandler (request.path.replace ('/', '_')]

Bien que non-trivial, il est encore plus facile que d'écrire un gestionnaire à partir de zéro: En particulier, vous ne devez écrire une seule ligne de lecture en mémoire tampon sujettes à erreur les étapes 3 et 4 sont nécessaires parce que FileUploadHandlers ne sont pas demande passés. informations par défaut, je crois, donc vous devrez le dire séparément si vous voulez utiliser l'URL d'une manière ou d'une autre

Je ne peux pas vraiment recommander d'écrire un FileUploadHandler personnalisé pour cela. C'est vraiment mélanger les couches de responsabilité. Relativement à la vitesse de téléchargement d'un fichier sur Internet, faire une copie de fichier local est insignifiant. Et si le fichier est petit, Django le gardera en mémoire sans l'écrire dans un fichier temporaire. J'ai le mauvais pressentiment que tout fonctionnera et que vous ne pourrez même pas mesurer la différence de performance.

+0

Bien sûr, je cherchais quelque chose ce n'est pas redondant avec django.core.files.uploadhandler.TemporaryFileUploadHandler – kmt

+0

Très bien. Je vais prendre cela comme * la * réponse. Je pensais dans le même sens, mais, étant très nouveau à Django, je voulais vérifier avec quelqu'un. BTW, d'où vient le ProgressBarUploadHandler? Je suppose, copier-coller de quelque part? C'est suffisant. J'apprécie l'effort de répondre à cette question. – kmt

+0

Bien que, sur une seconde cependant, je voudrais vraiment plus de discussion à ce sujet. Par exemple, le contenu de django/core/files/storage.py devrait-il être utilisé? De quoi s'agit-il? – kmt

8

fixe olooney exemple. Cela fonctionne maintenant

@csrf_exempt 
def upload_video_file(request): 
    folder = 'tmp_dir2/' #request.path.replace("/", "_") 
    uploaded_filename = request.FILES['file'].name 
    BASE_PATH = '/home/' 
    # create the folder if it doesn't exist. 
    try: 
     os.mkdir(os.path.join(BASE_PATH, folder)) 
    except: 
     pass 

    # save the uploaded file inside that folder. 
    full_filename = os.path.join(BASE_PATH, folder, uploaded_filename) 
    fout = open(full_filename, 'wb+') 

    file_content = ContentFile(request.FILES['file'].read()) 

    try: 
     # Iterate through the chunks. 
     for chunk in file_content.chunks(): 
      fout.write(chunk) 
     fout.close() 
     html = "<html><body>SAVED</body></html>" 
     return HttpResponse(html) 
    except: 
     html = "<html><body>NOT SAVED</body></html>" 
     return HttpResponse(html) 
+1

Je n'arrive pas où le ContentFile (request.FILES ['fichier '] .read()) vient de la fonction. –

+0

à partir de django.core.files.base import ContentFile – user2455668

Questions connexes