8

I'm using the ajax-upload code to do a simple AJAX file upload. The issue I'm coming across is the file isn't showing up on the backend after submitting.

The frontend code is pretty basic:

<div id="image_uploader">Upload More Images</div>
<script type="text/javascript" charset="utf-8">
    function createUploader(){            
        var uploader = new qq.FileUploader({
            element: document.getElementById('image_uploader'),
            action: '/add/image/1',
            debug: true,
            onSubmit : function () {
                progress.show();
            },
            onComplete : function () {
                progress.hide();
            },
            onCancel : function () {
                progress.hide();
            },
        });           
    };

    createUploader();
</script>

The backend code (currently in progress) is also pretty basic:

def add_image(request, id):
    print request
    if request.FILES:
        return HttpResponse("{success:true}")
    else:
        return HttpResponse("{success:false, message:'Unable to find FILES}")
Josh K
  • 28,364
  • 20
  • 86
  • 132

2 Answers2

12

For me, using code from Alex Kuhl, request.GET['qqfile'] had the filename and request.read() (in Django 1.3) returned the data.

request.FILES was only used in a scenario that hasn't yet happened for me. I'm using ajax-upload to talk directly to Photologue, and my code looks something like this:

def save_upload( uploaded, filename, raw_data ):
    """
    raw_data: if True, upfile is a HttpRequest object with raw post data
    as the file, rather than a Django UploadedFile from request.FILES
    """
    try:
        filename = os.path.normpath(os.path.join(IMAGE_UPLOAD_PATH, filename))
        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:
                (dirName, fileName) = os.path.split(filename)
                (fileBaseName, fileExtension)=os.path.splitext(fileName)
                #
                # right here, if fileBaseName is less than n characters, might want to slap on a date just for fun
                #
                try:
                    i_can_has_p = Photo.objects.get(title=fileBaseName)
                    title = fileBaseName + "_" + str(datetime.datetime.now().strftime("%Y%m%dT%H%M%S"))
                except Photo.DoesNotExist:
                    title = fileBaseName
                title_slug = slugify(title)
                p = Photo(title=title, title_slug=title_slug)
                p.image.save(filename,ContentFile(uploaded.read()))
            # if not raw, it was a form upload so read in the normal Django chunks fashion
            else:
                # TODO: figure out when this gets called, make it work to save into a Photo like above
                for c in uploaded.chunks( ):
                    dest.write( c )
    except IOError:
        # could not open the file most likely
        return False
    return True

def ajax_upload( request ):
  if request.method == "POST":
      # AJAX Upload will pass the filename in the querystring if it is the "advanced" ajax upload
      if request.is_ajax( ):
          # the file is stored raw in the request
          upload = request
          is_raw = True
          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:
              # FILES is a dictionary in Django but Ajax Upload gives the uploaded file an
              # ID based on a random number, so it cannot be guessed here in the code.
              # Rather than editing Ajax Upload to pass the ID in the querystring, note that
              # each upload is a separate request so FILES should only have one entry.
              # Thus, we can just grab the first (and only) value in the dict.
              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
  ret_json = { 'success': success, }
  return HttpResponse( json.dumps( ret_json ) )

In my case, ajax_upload is the function called by ajax's action: parameter

Thunder Rabbit
  • 5,405
  • 8
  • 44
  • 82
  • Where can I define `IMAGE_UPLOAD_PATH`? – Josh K Jan 20 '11 at 18:25
  • That constant isn't required, Thunder is just making use of it to build an absolute path. You can use a hard-coded value for the directory where you want uploads to be saved instead of the constant. If you do want to use it though, it would be something you place in your settings.py and then import in the view to use. Also thanks for the nod Thunder, glad others have found my post useful. – Alex Kuhl Jan 20 '11 at 18:31
  • @alex: Okay, I'm using `request.META['PWD'] + "/appName/static/images/" + filename`. – Josh K Jan 20 '11 at 18:38
  • @alex: thank you (and thanks for your original code!) @Josh: I have that defined in settings.py – Thunder Rabbit Jan 20 '11 at 18:56
  • and @Alex: Thanks for the code, I made a few tweaks and now it works great. – Josh K Jan 20 '11 at 20:07
  • @ThunderRabbit -- I'm using a simplified version of this code to implement raw ajax uploads. I'm having a problem with memory usage, though -- each uploaded file uses memory equal to the file size, and never lets it go. Most of the buffered file writing examples I've seen involve writing to disk, not saving directly into a Photo object. Any ideas on how to reduce memory usage, or maybe some way to use a buffered write to a Django ImageField (as in the Photo object)? – Clay Wardell Aug 08 '12 at 04:30
  • sorry I don't know; I haven't touched this code since I answered the question. – Thunder Rabbit Aug 08 '12 at 06:14
1

Andrew Valums has now got a django app at git hub

Robert Johnstone
  • 5,431
  • 12
  • 58
  • 88