2010-06-20 4 views
16

У меня возникли некоторые трудности с загрузкой файла AjaxForm и блоком blobstore. Я подозреваю, что это связано с тем, что обработчик загрузки blobstore (подкласс blobstore_handlers.BlobstoreUploadHandler) требует ответа на перенаправление, а не возврата какого-либо контента, но я не уверен. Я ожидаю получить XML-документ для работы, и, похоже, он появится в браузере так, как ожидалось, но я просто не могу его понять - подробности ниже.AjaxForm и app engine blobstore

Мое приложение двигатель обработчик загрузки Blobstore выглядит следующим образом -

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) 

Окончательный редирект на URI в моем приложении, который возвращает документ XML. Если посмотреть на вывод сервера, нет никаких указаний на то, что что-то не так - перенаправление обслуживается, и он возвращает XML-документ, как ожидалось, с правильным типом mime, поэтому представление формы выглядит хорошо, и ответ сервера на это представление выглядит хорошо.

Моей стороны клиент коды с помощью ajaxForm выглядит следующим образом (извините ее немного тупой, я не думаю, что проблема здесь, хотя) -

// 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)); 
     } 
     }); 
    }); 

Я установил «действие» на форме (и включить кнопка) после -

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

Я использую немного закрытия Google там, а также для регистрации и выставляя объекты. Все выглядит хорошо - как и ожидалось, оно правильно отправляется на сервер, и вызывается функция успеха. Если я посмотрю структуру документа в инструментах Chrome dev, я могу увидеть, как iFrame создается кратко для обработки загрузки и ответа файла.

Проблема в том, что я никогда не получаю XML-документ в ответе. Выход журнала выглядит следующим образом -

[ 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] 

жалоба хром о типе мима, вероятно, очень актуален, но я не делаю соединение :) - по крайней мере, это означает, что он получает документ XML в какой-то пункт. В Chrome зрения ресурсов, вы можете увидеть POST, и что ответ является 302 редирект, а затем последующий запрос GET - заголовок, который выглядит прекрасно -

вид
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 ресурсы не укажешь мне содержимое этого документа (просто пустое), но firefox делает, и XML-документ выглядит хорошо. Тем не менее, Firefox дает тот же конечный результат - null для ajaxSubmit() responseText.

Я полагаю, что у меня просто мозг исчезает где-то, но это действительно заставило меня задохнуться. Любые указатели для получения, что XML-документ, было бы здорово - веселит,

Colin

+0

Я предполагаю, что Ajaxform не обрабатывает перенаправляет должным образом - либо самостоятельно, либо потому, что он использует флэш-компонент, который не обрабатывает их. Попробуйте изменить обработчик загрузки на обычный обработчик запросов и вернуть документ напрямую, а не перенаправление, и посмотреть, не имеет ли значения - это, по крайней мере, скажет вам, является ли это перенаправлением или нет. –

+0

Yep ok - подтвердил, что он был перенаправлен, как и предполагалось (он не использует вспышку). Почему blobstore UploadHandler требует перенаправления? Кто-нибудь получил загрузку стиля ajax, работая с blobstore? то есть пользователь не испытывает перенаправления или обновления страницы? Спасибо. – hawkett

+0

http://forum.jquery.com/topic/jquery-form-plugin-and-app-engine-blobstore#14737000001093602 - автор подтверждения не может преследовать редирект. Кажется, что поведение * принудительного перенаправления переполнено API-интерфейсом blobstore? – hawkett

ответ

0

Если вы 5 месяцев застряли на одной и той же проблемой .. Я думаю, вы должны спросить здесь:

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

+0

Эта проблема почти наверняка не проблема хром - она ​​встречается в других браузерах. Проблема, в зависимости от того, как вы смотрите на нее, - это либо blobstore api, требующая перенаправления, либо AjaxForm, не преследуя эту перенаправление. В отсутствие каких-либо оправданий от google я склоняюсь к первому - кажется, что они создали обруч, чтобы прыгать без причины. – hawkett

4

Вот метод, который я использовал (только проверенный в Chrome), слегка измененный. Это не AjaxForm, но он работает.

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); 
} 

entityKey доступен как пары на сервере. Параметр «файлы» исходит из атрибута «files» элемента входной формы типа файла (в качестве массива для поддержки нескольких).Параметр «progress_callback» - это функция, которая принимает объект, который имеет (по крайней мере) «загруженное» и «общее» поле (единица - байты). Он не заботится об ответе сервера.

+0

Итак, вместо того, чтобы ждать ответа, используйте обратный вызов прогресса, чтобы определить, когда загрузка завершена (загружена == total?), А затем запросить обновленный объект отдельно - как вы говорите, полностью игнорировать ответ сервера? Ta. – hawkett

1

вот как я решил. Я добавил случайный id, созданный в javascript, отправляемый вместе с файлом. после завершения загрузки настройте мой сервер на некоторое время, чтобы запомнить связь этого случайного идентификатора и загруженного файла. Я отправляю другой запрос на предопределенный URL-адрес, например mysite.com/blobdata/that_random_id_i_renerated, чтобы запросить только что загруженный файл. это сработало.

Смежные вопросы