3 votes

django ajax/jquery file upload

J'essaie de reproduire l'exemple donné par Alex Kuhl dans son excellent article : http://kuhlit.blogspot.com/2011/04/ajax-file-uploads-and-csrf-in-django-13.html

Cependant, je ne parviens pas à reproduire ce phénomène.

####### upload_page.html  

{% extends "base.html" %}
{% load i18n %}
{% block title %}Blog Post: Upload Files.{% endblock %}

{% block content %} 
<div id="maintext"> 
<p>To upload a file, click on the button below.</p>
<div id="file-uploader">
<noscript>
<p>Please enable JavaScript to use file uploader.</p>
<!-- or put a simple form for upload here -->
</noscript>
</div>
<script>
    function createUploader(){
    var uploader = new qq.FileUploader( {
        action: "{% url ajax_upload %}",
        element: $('#file-uploader')[0],
        multiple: false,
        onComplete: function( id, fileName, responseJSON ) {
          if( responseJSON.success )
        alert( "success!" ) ;
          else
        alert( "Sorry, your upload has failed! Please contact us by telephone or email." ) ;
        },
        onAllComplete: function( uploads ) {
          // uploads is an array of maps
          // the maps look like this: { file: FileObject, response: JSONServerResponse }
          alert( "All complete!" ) ;
        },
        params: {
          'csrf_token': '{{ csrf_token }}',
          'csrf_name': 'csrfmiddlewaretoken',
          'csrf_xname': 'X-CSRFToken',
        },
      } ) ;
    }

    // in your app create uploader as soon as the DOM is ready
    // don't wait for the window to load
    window.onload = createUploader;
</script>
</div>
{% endblock %}

Le fichier views.py est le suivant :

############### views.py
def upload_page( request ):
    ctx = RequestContext( request, {
        'csrf_token': get_token( request ),
    })
    return render_to_response( 'success/upload_page.html', ctx )

def save_upload( uploaded, filename, raw_data ):
    filename = settings.UPLOAD_STORAGE_DIR
    '''
    raw_data: if True, uploaded is an HttpRequest object with the file being
        the raw post data
        if False, uploaded has been submitted via the basic form
        submission and is a regular Django UploadedFile in request.FILES
    '''
    try:
        from io import FileIO, BufferedWriter
        with BufferedWriter( FileIO( filename, "wb" ) ) as dest:
            # if the "advanced" upload, read directly from the HTTP request
            # with the Django 1.3 functionality
            if raw_data:
                foo = uploaded.read( 1024 )
                while foo:
                    dest.write( foo )
                    foo = uploaded.read( 1024 )
            # if not raw, it was a form upload so read in the normal Django chunks fashion
            else:
                for c in uploaded.chunks( ):
                    dest.write( c )
            # got through saving the upload, report success
            return True
    except IOError:
        # could not open the file most likely
        pass
        return False

def ajax_upload( request ):
    if request.method == "POST":   
        if request.is_ajax( ):
            # the file is stored raw in the request
            upload = request
            is_raw = True
            # AJAX Upload will pass the filename in the querystring if it is the "advanced" ajax upload
            try:
                filename = request.GET[ 'qqfile' ]
            except KeyError:
                return HttpResponseBadRequest( "AJAX request not valid" )
        # not an ajax upload, so it was the "basic" iframe version with submission via form
        else:
            is_raw = False
            if len( request.FILES ) == 1:
                upload = request.FILES.values( )[ 0 ]
            else:
                raise Http404( "Bad Upload" )
            filename = upload.name

        # save the file
        success = save_upload( upload, filename, is_raw )

        # let Ajax Upload know whether we saved it or not
        import json
        ret_json = { 'success': success, }
        return HttpResponse( json.dumps( ret_json ) )

Le fichier urls.py est le suivant :

####### urls.py

urlpatterns = patterns('',
(r'media/(?P<path>.*)$', 'django.views.static.serve', {'document_root':   settings.MEDIA_ROOT}),
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
url(r'^$', index,name='home'),
url( r'^ajax_upload$', ajax_upload, name="ajax_upload" ),
url( r'^upload/$', upload_page, name="upload_page" ),
(r'^admin/', include(admin.site.urls)),
(r'^accounts/', include('regfields.urls')),

# Examples:
# url(r'^$', 'mysite.views.home', name='home'),
# url(r'^mysite/', include('mysite.foo.urls')),

# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

# Uncomment the next line to enable the admin:
# url(r'^admin/', include(admin.site.urls)),

Le code est également activé : http://dpaste.com/600444/

Bien que tout semble correct, le téléchargement échoue toujours.

J'utilise : filename = settings.UPLOAD_STORAGE_DIR, où UPLOAD_STORAGE_DIR est défini dans settings.py comme '/media/'.

Quelqu'un pourrait-il m'indiquer où je me trompe (Désolé, je suis nouveau dans la programmation web et je n'ai jamais utilisé JS auparavant, mais je peux programmer en python raisonnablement !)

4voto

Daniel Hepper Points 4992

Il y a une faute de frappe dans votre Javascript. Il devrait se lire {% csrf_token %} au lieu de {{ csrf_token }} .

Editer : Suite à vos commentaires, j'ai regardé de plus près l'article que vous avez mis en lien.

Vous devez inclure la bibliothèque fileuploader.js . Il remplacera la div de remplacement avec l'id file-uploader avec un formulaire doté des gestionnaires d'événements appropriés. La création d'un formulaire en HTML simple ne fonctionnera pas.

Je vous suggère de jeter un coup d'œil à l'exemple dans le dépôt Github : https://github.com/alexkuhl/file-uploader/tree/master/client

1voto

Cianan Sims Points 3279

Vous devez ajouter return True à l'instruction if qui vérifie s'il s'agit de données brutes, sinon elle renverra False même si le téléchargement est réussi :

...
if raw_data:
    foo = uploaded.read(1024)
    while foo:
        dest.write(foo)
        foo = uploaded.read(1024) 
    return True
...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X