Автоматическая загрузка не работает для Django FileResponse

Мне нужно, чтобы Django автоматически загружал сгенерированный файл.

Пробовал разные решения в интернете, ни одно не работает.

Views.py

def validate(request):
    if request.method == 'POST':
        filename = request.POST.get('source_file')
        file_path = os.path.join(settings.MEDIA_ROOT, 'SourceFiles', filename)
        region = request.POST.get('region')
        product_type = request.POST.get('product_type')
        result = validateSource.delay(file_path, region, product_type)
        output_filepath, log_filepath = result.get()
        if os.path.exists(output_filepath) and os.path.exists(log_filepath):
            zip_filename = zipFiles([output_filepath, log_filepath], filename)
            zip_filepath = os.path.join(settings.MEDIA_ROOT, zip_filename)
            response = FileResponse(open(zip_filepath, 'rb'), as_attachment=True)
            return response
        raise Http404

Шаблон: код формы POST.

     $(document).on('submit', '#productForm', function(e){
       e.preventDefault();
       var inputFilePath = document.getElementById('sourceFileInput').files.item(0).name;
        $.ajax({
            method: 'POST',
            url: 'validate/',
            data: {
              source_file: inputFilePath,
              region: $("#Region-choice").val(),
              product_type: $("#Product-type").val()}
            })
            .done(function(){
                document.getElementById('lblStatus').innerHTML = "Result: <br/>"
                document.getElementById('lblStatusContent').innerHTML = "Success!"

            })
            .fail(function(req, textStatus, errorThrown) {
                document.getElementById('lblStatus').innerHTML = "Result: <br/>"
                alert("Something went wrong!:" + textStatus + '  ' + errorThrown )
            });
    });
 });

"не работает" не очень описательно. Что просходит?

dirkgroten 22.05.2019 16:35

@dirkgroten хорошо, ничего не происходит, когда возвращается ответ. Я ожидаю, что файл будет автоматически загружен, когда вернется FileResponse.

flgn 22.05.2019 16:37

но если FileResponse возвращается, вы либо увидите файл в своем браузере, либо он будет загружен. Что вы видите на вкладке «Сеть» вашего браузера? какие заголовки ответа? Вы видите, что файл возвращается туда? И установлен ли заголовок Content-Disposition для ответа?

dirkgroten 22.05.2019 16:39

Не могли бы вы сделать запрос GET? Он возвращает 404, потому что файл не существует? Вы пытались сделать простое представление, которое возвращает FileResponse, а затем работать в обратном направлении, добавляя больше своей логики?

schillingt 22.05.2019 16:40

@dirkgroten да, я вижу файл в заголовках ответов. А для Content-Dispositioin, согласно официальной документации, Если as_attachment=True, устанавливается заголовок Content-Disposition, который просит браузер предложить файл пользователю для загрузки., кажется, мне больше не нужно устанавливать его вручную. И в ответе написано Content-Disposition: вложение; имя_файла="Final.zip", выглядит правильно.

flgn 22.05.2019 16:43

что делает запрос POST? Если это обычная отправка формы html или это xhr?

dirkgroten 22.05.2019 16:46

@dirkgroten да, из обычной HTML-формы.

flgn 22.05.2019 16:47

@shillingt Файл существует, и он также находится в заголовках ответов.

flgn 22.05.2019 16:49

вы пробовали разные браузеры? Мне интересно, всегда ли ответ на POST с файлом для загрузки обрабатывается одинаково. Обратите внимание, что, как правило, вы должны перенаправлять всегда на POST, чтобы у вас был GET для получения страницы успеха. Это потому, что в противном случае вы «сломаете» кнопку «Назад».

dirkgroten 22.05.2019 17:30

а вы пробовали что-то еще, кроме zip-файла? Я думаю, что браузер может быть причиной здесь.

dirkgroten 22.05.2019 17:31

@dirkgroten Да, тоже пробовал в FF, все то же самое. Для перенаправления я сомневаюсь, что мне следует это использовать, потому что я хочу оставаться на той же странице и не обновлять страницу.

flgn 22.05.2019 17:33

@dirkgroten Пробовал с простым и небольшим файлом .txt, волшебства не произошло...

flgn 22.05.2019 17:38

Также может быть лучше разместить код шаблона здесь...

flgn 22.05.2019 17:45

вы сказали, что это обычная запись в формате html, но, видимо, это не так: вы делаете запрос XHR!

dirkgroten 22.05.2019 17:52

@dirkgroten хорошо, тогда я их перепутал ... Может ли быть проблема в этом?

flgn 22.05.2019 17:55

да, конечно, вы ничего не делаете с файлом, который возвращается вашим обработчиком done.

dirkgroten 22.05.2019 17:56

Возможный дубликат Скачать файл с помощью jQuery.Ajax

dirkgroten 22.05.2019 17:59
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
1
17
2 136
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

def validate(request):
    if request.method == 'POST':
        filename = request.POST.get('source_file')
        file_path = os.path.join(settings.MEDIA_ROOT, 'SourceFiles', filename)
        region = request.POST.get('region')
        product_type = request.POST.get('product_type')
        result = validateSource.delay(file_path, region, product_type)
        output_filepath, log_filepath = result.get()
        if os.path.exists(output_filepath) and os.path.exists(log_filepath):
            zip_filename = zipFiles([output_filepath, log_filepath], filename)
            zip_filepath = os.path.join(settings.MEDIA_ROOT, zip_filename)
            with open(zip_filepath, 'rb') as fh:
                response = HttpResponse(fh.read(), content_type="application/force-download")
                response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(zip_filepath)
                return response
        raise Http404

Попробуйте встроенный вместо вложения

Amine Messaoudi 22.05.2019 17:17

В сети ответ уже показывает Content-Disposition: inline;

flgn 22.05.2019 17:20

Это может сломаться, если путь к файлу содержит точку с запятой.

Flimm 02.11.2021 15:01
Ответ принят как подходящий

Невозможно загрузить файлы на ваш компьютер с помощью запроса ajax (XHR). Таким образом, вам нужно фактически перенаправить пользователя (настройка window.location) в представление, которое загружает файл. Или вы можете добавить в результате успешного POST кнопку текущую страницу, чтобы пользователь мог загрузить файл. В любом случае вам нужно переместить загрузку файла в другое представление, чтобы его можно было получить с помощью стандартного запроса GET.

Но ваш код для возврата файла в Django (с использованием FileResponse) правильный.

Также есть объяснение с альтернативным способом сделать это здесь

Хорошо, допустим, кнопка загрузки появляется после успешного POST, как можно отправить возвращенный FileResponseфункции нажатия кнопки? Возможно глупый вопрос, но я новичок в JS...

flgn 23.05.2019 14:14

Кнопка — это просто ссылка <a href="> на другое представление Django (GET), где вы возвращаете FileResponse. Поэтому вам нужно написать другое представление, которое возвращает файл. Это означает, что ваше представление POST должно возвращать какой-то идентификатор файла, который затем можно использовать в GET.

dirkgroten 23.05.2019 14:30

Итак, вот так: 1. Первая функция View принимает запрос POST для создания файла, который будет загружен; 2. Напишите вторую функцию в представлении, чтобы вернуть FileResponse 3. Используйте window.location в успешном POST, чтобы перенаправить на URL-адрес функции представления, созданной на предыдущем шаге, чтобы ПОЛУЧИТЬ файл (не знаю, как, проверим.)

flgn 23.05.2019 15:44

Да, это одно из возможных решений. Ваш 1-й просмотр должен вернуться. jsonResponse с URL-адресом файла (чтобы ваше второе представление «знало», какой файл отправить обратно). Если вы используете window.location, пользователь увидит обновление страницы (на пустую страницу) перед началом загрузки. Вот почему я подумал, что кнопка будет работать лучше, поскольку пользователь просто останется на текущей странице. Но легко попробовать оба, чтобы решить, что лучше для пользователя.

dirkgroten 23.05.2019 15:48

Другие вопросы по теме