2010-06-20 9 views
16

Ich habe einige Schwierigkeiten mit AjaxForm Datei-Upload und der App-Engine Blobstore. Ich vermute, die Schwierigkeit liegt darin, dass der Upload-Handler für blobstore (Unterklasse von blobstore_handlers.BlobstoreUploadHandler) eine Weiterleitungsantwort vorschreibt, anstatt irgendeinen Inhalt zurückzusenden, aber ich bin mir nicht sicher. Ich erwarte ein XML-Dokument, mit dem ich arbeiten kann, und es scheint wie erwartet beim Browser angekommen zu sein, aber ich kann es einfach nicht erreichen - Details unten.AjaxForm und App Engine Blobstore

Meine app Engine Blobstore Upload-Handler ist wie folgt -

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler): 
    def post(self): 
    upload_files = self.get_uploads('file') # 'file' is file upload field in the form 
    blob_info = upload_files[0] 

    entity_key = self.request.get("entityKey") 

    // Update a datastore entity with the blobkey (not shown) 

    // redirect to the uri for the updated entity 
    self.redirect('%s.xml' % entity_key) 

Die letzte Umleitung zu einem uri in meiner Anwendung, die ein XML-Dokument zurückgibt. Betrachtet man die Serverausgabe, gibt es keinen Hinweis darauf, dass irgendetwas falsch ist - die Weiterleitung wird bedient und das xml-Dokument wird wie erwartet mit dem korrekten Mime-Typ zurückgegeben - so sieht die Formularübermittlung gut aus und die Serverantwort auf diese Übermittlung sieht aus gut.

Code Meine Client-Seite mit ajaxForm wie folgt aussieht (sorry es ist ein wenig stumpf, ich denke nicht, das Problem ist hier allerdings ist) -

// Create the form 
var dialogForm = $("<form method='POST' enctype='multipart/form-data'>") 
    .append("<span>Upload File: </span><input type='file' name='file'/><br>") 
    .append("<input type='hidden' name='entityKey' value='" + entityKey + "'/>") 
    .append("<input type='hidden' name='entityField' value='image'/>") 
    .append("<input type='button' value='Wait...' disabled='disabled'/>");; 

dialogForm.ajaxForm(); 

// Turn the form button into a nice jQuery UI button and add a click handler 
$("input[type=button]", dialogForm[0]).button() 
    .click(function() { 
     log.info("Posting to : " + dialogForm.attr('action')); 
     dialogForm.ajaxSubmit({ 
     success: function(responseText, statusText, xhr, $form) { 
      log.info("Response: " + responseText + ", statusText: " + statusText + ", xhr: " + goog.debug.expose(xhr) + ", form:" + goog.debug.expose($form)); 
     } 
     }); 
    }); 

ich die ‚Aktion‘ auf dem Formular gesetzt (und ermöglichen die Taste) danach -

$.get('/blob_upload_url', function(data) { 
    dialogForm.attr("action", data); 
    $("input[type=button]", dialogForm[0]).attr("value", "Upload").button("option", "disabled", false); 
}; 

ich bin auch für die Protokollierung und das Aussetzen Objekte in ein wenig google-Verschluss verwendet wird. Alles sieht gut aus - wie erwartet wird es korrekt auf dem Server gepostet und die Erfolgsfunktion aufgerufen. Wenn ich die Dokumentstruktur in den Chrome-Entwicklungstools beobachte, kann ich sehen, dass der iFrame kurz erstellt wird, um den Datei-Upload und die Antwort zu verarbeiten.

Das Problem ist, dass ich nie das XML-Dokument in der Antwort bekomme. Die Protokollausgabe ist wie folgt -

[ 18.642s] [Panel] Response: null, statusText: success, xhr: 0 = [object HTMLFormElement] 
length = 1 
selector = 
jquery = 1.4.2, form:0 = [object HTMLFormElement] 
length = 1 
selector = 
jquery = 1.4.2 
Resource interpreted as document but transferred with MIME type application/xml [ABCdefGH] 

Die Beschwerde wurde von Chrom über den MIME-Typ ist wahrscheinlich Super relevant, aber ich mache nicht die Verbindung :) - zumindest bedeutet es, dass es das XML-Dokument wird immer an Irgendwann. In Chrome Ressourcen-Ansicht können Sie die POST sehen, und dass die Antwort eine 302-Umleitung, und dann die nachfolgende GET-Anforderung - der Header davon sieht gut aus -

Request URL:http://localhost:8081/_ah/upload/ABCdefGH 
Request Method:GET 
Status Code:200 OK 
Request Headers 
Referer:http://localhost:8081/ 
User-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.70 Safari/533.4 
Response Headers 
Cache-Control:no-cache 
Content-Length:2325 
Content-Type:application/xml 
Date:Sun, 20 Jun 2010 20:47:39 GMT 
Expires:Fri, 01 Jan 1990 00:00:00 GMT 
Server:Development/1.0 

Chrome Ansicht Ressourcen zeigt mir nicht den Inhalt des Dokuments (nur leer) aber Firefox tut und das XML-Dokument sieht gut aus. Firefox gibt jedoch das gleiche Endergebnis - null für den ajaxSubmit() responseText.

Ich denke, ich habe nur ein Gehirn hier irgendwo verblassen, aber es hat mich wirklich ratlos. Alle Hinweise für diese XML-Dokument bekommen wäre toll - Prost,

Colin

+0

Ich nehme an, dass Ajaxform Umleitungen nicht richtig behandelt - entweder allein oder weil es eine Flash-Komponente verwendet, die sie nicht behandelt. Versuchen Sie, Ihren Upload-Handler in einen normalen Anforderungshandler zu ändern und das Dokument direkt anstelle einer Weiterleitung zurückzusenden, und sehen Sie, ob dies einen Unterschied macht - das wird Ihnen zumindest sagen, ob es sich um die Weiterleitung handelt oder nicht. –

+0

Yep ok - bestätigt, dass es umgeleitet wurde, wie vorgeschlagen (es verwendet keinen Blitz). Wie kommt es, dass der UploadHandler von blobstore eine Weiterleitung beauftragt? Jeder hat einen Ajax-Style-Upload mit dem Blobstore? d.h. der Benutzer erfährt keine Umleitung oder Seitenaktualisierung? Danke. – hawkett

+0

http://forum.jquery.com/topic/jquery-form-plugin-and-app-engine-blobstore#14737000001093602 - Autor bestätigt, dass es Redirect nicht verfolgen kann. Scheint das * erzwungene * Redirect-Verhalten mit der Blobstore-API übertrieben zu sein? – hawkett

Antwort

0

Wenn Sie 5 Monate auf dem gleichen Problem stecken .. Ich denke, Sie sollten hier fragen:

http://www.google.com/support/forum/p/Chrome/

+0

Dieses Problem ist fast sicher kein Chrome-Problem - es tritt in den anderen Browsern auf. Das Problem, je nachdem, wie Sie es betrachten, ist entweder die Blobstore-API, die eine Umleitung vorschreibt, oder das AjaxForm, das diese Umleitung nicht verfolgt. In Ermangelung irgendeiner Rechtfertigung von Google lehne ich mich zu dem ehemaligen hin - scheint, dass sie einen Reifen geschaffen haben, um ohne Grund durch zu springen. – hawkett

4

Hier ist eine Methode, die ich verwendet habe (nur in Chrome getestet) leicht modifiziert. Es ist nicht AjaxForm, aber es funktioniert.

function upload_files(entityKey, files, url, progress_callback) { 
    var xhr = new XMLHttpRequest(), formData = new FormData(); 
    xhr.upload['onprogress'] = progress_callback; 

    formData.append('entityKey', entityKey); 
    $.each(files, function(i, file) { formData.append('file[]', file);}); 

    xhr.open("post", url, true); 
    xhr.setRequestHeader("Cache-Control", "no-cache"); 
    xhr.send(formData); 
} 

Die entityKey ist als param auf dem Server verfügbar. Der Parameter 'files' stammt vom Attribut 'files' des Eingabeformularelements vom Typ datei (als ein Array, das mehrere unterstützt).Der Parameter 'progress_callback' ist eine Funktion, die ein Objekt mit (mindestens) 'geladenem' und 'totalem' Feld (Einheit ist Bytes) übernimmt. Es kümmert sich nicht um die Serverantwort.

+0

Ok, also anstatt auf die Antwort zu warten, verwenden Sie den Fortschritts-Callback, um festzustellen, wann der Upload abgeschlossen ist (geladen == Summe?), Und dann separat nach der aktualisierten Entität abzufragen - wie Sie sagen, die Serverantwort vollständig ignorieren? Ta. – hawkett

1

hier ist, wie ich es gelöst habe. Ich fügte eine zufällige id hinzu, die in Javascript erzeugt wurde, das zusammen mit Datei gesendet wurde. Sobald der Upload abgeschlossen ist, konfigurieren Sie meinen Server für eine Weile, um sich die Zuordnung dieser zufälligen ID und der hochgeladenen Datei zu merken. Ich sende eine weitere Abfrage an eine vordefinierte URL wie mysite.com/blobdata/that_random_id_i_renated, um die gerade hochgeladene Datei anzufordern. es funktionierte.

Verwandte Themen