Нужна помощь в понимании загрузки файлов в Python Flask, без / с Javascript + Ajax

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

Я начал это, используя учебник / руководство, которое я нашел в Интернете, здесь

Однако я был очень удивлен, обнаружив, что это работает без JavaScript. Я не понимаю, как нажатие кнопки отправляет запрос о появлении всплывающего окна с просьбой выбрать файл. Откуда он знает, что кнопка предназначена для загрузки файлов? Нет, где в HTML я даю ему очевидный атрибут, который говорит ему загружать файл, и нигде в python/Flask я не выбираю кнопку, используемую для загрузки.

К моему удивлению, я также заметил, что в приведенном примере маршрут ДОЛЖЕН называться "/upload" для работы. Опять же, я не вижу, где что-то из этого определено или где я могу это изменить. Единственными файлами, которые используются для демонстрации по этой ссылке (которая является основой моего веб-приложения), являются app.py и index.html (файл setup.py, по-видимому, не нужен для запуска веб-сервера)

По мере развития моего веб-приложения я пытался добавить файл javascript, который получал бы ответ от маршрута / uploads и отображал его в интерфейсе, но вскоре столкнулся с проблемами. Кажется, я могу запускать / выгружать только из той загадочной силы, которая сейчас его запускает. Мой javascript не может получить к нему доступ, и поэтому у меня нет возможности получить ответ в JS, чтобы я мог отобразить его на внешнем интерфейсе так, как я хочу.

Может кто-нибудь помочь мне понять, как работает сервер загрузки файлов по ссылке, чтобы я мог изменить его для работы со своим JavaScript?

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

Я не чувствую, что стоит публиковать слишком много моего кода на python и HTML, так как все важные вещи есть в этой ссылке, но файл javascript приведен ниже.

    "use strict";

var main = function() {
    console.log("i am functioning!")

    var show_similar_img = function(){
        //Read megastatus
        $.ajax({
                method: "GET",
                url: "/upload",
                // contentType: 'application/json',
                dataType: "string"
        })
        .done(function(media_info){
            console.log(media_info)
        });
    }

    $("#upload-btn").on("click",function(){
        console.log("button pressed!")
        show_similar_img()
    })
}

console.log("i am being run!")
$(document).ready(main);

1 ответ

Решение

<input> элемента type атрибут fileЭто то, как браузер знает, как обращаться с ним особым образом - как вы заметили, открывая всплывающее модальное окно, которое предлагает пользователю выбрать файл.

Маршрут должен называться " загрузить", потому что <form> элемента action Значение атрибута также называется загрузкой. Вы можете изменить название маршрута, если вы также изменили действие формы.

Фактически вы можете получить доступ к информации о файле (для файла, связанного с элементом ввода), используя JavaScript благодаря File API. В Mozilla Developer Network есть отличное руководство: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Что касается вашей фактической реализации: во-первых, вы также захотите запретить обработку отправки формы "обычным" (синхронным) способом, поэтому вам нужно вызвать preventDefault на мероприятии:

$("#upload-btn").on("click",function(event) {
    event.preventDefault();
    console.log("button pressed!")
    show_similar_img()
 })

Во-вторых, я предполагаю, что вы действительно хотите отправить файл на сервер (запущенный на Python/Flask), поэтому вы хотите, чтобы ваш AJAX-запрос был POST, а не GET. Поэтому вам нужно изменить show_similar_img, чтобы отправить запрос как POST, а также включить файл в данные запроса, используя вышеупомянутый File API. Что-то вроде этого:

var show_similar_img = function(){
    var formData = new FormData();
    var file = $("input[type='file']")[0].files[0];
    formData.append("file", file);

    $.ajax({
        url : "/upload",
        type : "POST",
        data : formData,
        contentType: false,
        processData: false
    })
    .done(function(media_info){
        console.log(media_info)
    });

}

Редактировать - я должен добавить, что я не очень знаком с Flask или тонкостями его request объект. Я предполагаю, что независимо от того, загружен ли файл как часть отправки формы или асинхронного запроса, он все равно будет доступен на request.files['file'], но возможно, что Flask не делает асинхронно загруженные файлы доступными в request.files толковый словарь. Я очень уверен, однако, что файл будет доступен где-то на request объект, поэтому вам может понадобиться обратиться к документации Flask. Вы также можете использовать pdb добавить точку останова в коде на стороне сервера и проверить request объект, чтобы увидеть, что он держит (и где он его держит).

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