Скачать несколько файлов в одном запросе (jQuery / Python) - PullRequest
4 голосов
/ 30 марта 2011

Привет, ребята.По сути, мне нужно создать для пользователя способ открывать веб-страницу, выбирать из списка флажков в форме и после отправки формы загружать все эти файлы вместе.

Вотограничения, наложенные на меня клиентом:

  • Платформа в основном для мобильных устройств
  • Нет файлов ZIP (поскольку мы не можем предположить, что мобильное устройство может обрабатывать почтовые индексы)
  • Файлы ДОЛЖНЫ быть загружены, а не потоковыми

Поэтому я создал веб-приложение, используя XHTML / CSS w / jQuery Mobile 1.0a3 на внешнем интерфейсе и Apache w / Python 2.6 на внутреннем.Целевые файлы, которые будут загружены, - это файлы .mp3.

Мне удалось выполнить желаемый эффект на рабочем столе, используя скрытые фреймы, передаваемые с сервера и загружаемые с помощью jQuery через AJAX ... но это не так.не работает в браузере Android по умолчанию или в браузере Dolphin.

Я убедился, что мой конфиг Apache будет вызывать поведение при загрузке:

<Files *.mp3>
    ForceType application/octet-stream
    Header set Content-Disposition attachment
</Files>

Кроме того, модуль Apache "headers" включен (необходим дляПараметр конфигурации "Header set"), так что это не проблема.

Я выполняю AJAX-вызов на сервер со всеми выбранными элементами в качестве параметров, и когда сервер читает массив элементов, он запрашиваетбаза данных для информации о каждом элементе (например, URL каждого mp3-файла).Затем код iframe создается в бэкэнде для каждого mp3-файла и затем отправляется обратно в функцию $.load() jQuery для загрузки новых iframes (загружающих mp3-файлы).

Не вставляя слишком много кода, вот оченькраткий тестовый пример того, что я делаю:

на стороне сервера

def download(req):
    resultDiv = """<div id="downloads">"""
    queryIds = []
    for element in req.form:
        # "element" contains the id number that matches database record
        trackId = re.match('^track(\d+)', element).group(1)
        queryIds.append(trackId)

    conn = MySQLdb.connect(host='localhost', user='fake', passwd='fake', db='fake')
    cursor = conn.cursor()

    buildQuery = """\
        SELECT filePath FROM tracks
        WHERE trackNum in ("""

    buildQuery += ','.join(queryIds)
    buildQuery += ')'

    cursor.execute(buildQuery)
    downloadRows = cursor.fetchall()

    for track in downloadRows:
        resultDiv += """
            <iframe src="%s"></iframe>
        """ % track[0]

    return resultDiv

на стороне клиента

<!DOCTYPE html>
<html>
    <head>
        <!-- INCLUDES FOR JQUERY MOBILE AND JQUERY -->
        <style type="text/css">
            .invisible {
                display: none;
            }
        </style>
        <script type="text/javascript">
            $(document).ready(function() {
                $('#albumForm').submit(function(e) {
                    e.preventDefault();

                    // this will hold the selected items on the form
                    selTracks = {};

                    $('#trackList').find(':checked').each(function() {
                        selTracks[this.id] = 'on';
                    });

                    // load the iframes into a 'div' set aside for that purpose
                    $('#results').load('control.py/download #tracks', selTracks);
                });
            });
        </script>
    </head>
    <body>
        <div data-role='page' id='page'>
            <div data-role='header' id='header'>
            </div>
            <div data-role='content' id='content'>
                <div id='container'>
                    <form id='albumForm'>
                        <div data-role='controlgroup' data-role='fieldcontain'>
                            <input type='checkbox' name='track1' id='track1' />
                            <label for='track1' id='track1label'>Track 1</label>
                            <input type='checkbox' name='track2' id='track2' />
                            <label for='track2' id='track2label'>Track 2</label>
                            <input type='checkbox' name='track3' id='track3' />
                            <label for='track3' id='track3label'>Track 3</label>

                            <input type='submit' id='downloadButton' value='Download' />
                        </div>
                    </form>
                </div>
                <div id='results' class='invisible'>
                </div>
            </div>
            <div data-role='footer' id='footer'>
            </div>
        </div>
    </body>
</html>

Извините, код настолько общий (и значительно сокращен), но я не уполномочен публиковать реальный код (вы знаете, как он).Но это в основном суть этого;Я считаю, что проблема кроется где-то в интерпретации мобильного браузера или где-то в заголовках HTTP?Это работает в Chrome и Firefox на рабочем столе и фактически работает точно так же, как и ожидалось в Fennec для Android (он загружает все файлы без дальнейшего взаимодействия и просто отображает их в панели уведомлений).Я просто не могу предположить, что все используют Fennec (а это не так, смеется).

В дополнение к вышесказанному, я попробовал следующее (которые все работали на настольном компьютере, но не на мобильном):

  • JSON возвращается с сервера, а iframes, созданные на клиенте с помощью jQuery
  • JSON, возвращаются с сервера и цикл for для вызова window.open() для каждого URL
  • JSON вернулся с сервера, и <a> теги, созданные jQuery и click() сработали
  • Использовать разные DOCTYPEs

Вот что я пробовал, но это неработать на настольном компьютере или на мобильном устройстве:

  • Изменение location.href или window.location (очевидно, это можно сделать только один раз)
  • Вызов req.sendfile() на сервере (возможно, яя делаю это неправильно?)
  • Возвращение multipart / form-data и сброс двоичных данных с заданной границей с сервера (ОЧЕНЬ грязно, и, возможно, я тоже делаю это неправильно?)

Все еще нет радости;Чего мне не хватать?

PS Пожалуйста, не сердитесь на меня за использование скрытых фреймов ...

РЕДАКТИРОВАТЬ: Я даже буду в порядке с другим родным протоколом браузера, который я могу настроитьна сервере, например FTP.Все идеи приветствуются.

ОБНОВЛЕНИЕ: Я пытаюсь установить FTP-соединение от клиента к серверу и запустить «mget».Я знаю, что net2ftp может сделать это ... теперь, чтобы понять это;) Все еще готов к новым идеям.

1 Ответ

0 голосов
/ 06 апреля 2011

Это лимит клиента. Существует ограничение на количество скачиваний для каждого домена. Попробуйте отправить файлы из разных доменов, например, d1.example.com и d2.example.com. Все они могут обслуживаться с одного виртуального хоста:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias d1.example.com d2.example.com
    ...
</VirtualHost>
...