Un approccio per inviare i contenuti di un file sul server al client in tempo reale

2

Ho un fronte relativamente semplice nel buon vecchio JQuery, che fa una richiesta POST a un server web Flask Python, che esegue uno script Python usando modulo sottopubblicazione . Ecco l'intero percorso per l'illustrazione:

@app.route("/adyen_request_download", methods=["POST", "GET"])
def adyen_request_download():
    merchant_manager = MerchantManager()
    error = None
    if request.method == "POST":
        pfjs = []
        prefixes = []
        extensions = []
        ftpd = "/var/ftp/ADYEN"
        date_type = "specific"
        specific_date = ""
        range_from = ""
        range_to = ""
        for result in request.get_json():
            if result["name"] == "pfj-select":
                pfjs.append(result["value"])
            if result["name"] == "prefix-select":
                prefixes.append(result["value"])
            if result["name"] == "extension-select":
                extensions.append(result["value"])
            if result["name"] == "date-group":
                if result["value"] == "specific":
                    date_type = result["value"]
                elif result["value"] == "range":
                    date_type = result["value"]
            if result["name"] == "specific-date":
                specific_date = result["value"]
            if result["name"] == "range-from":
                range_from = result["value"]
            if result["name"] == "range-to":
                range_to = result["value"]

        dev = True # Checar pra False em modo de produção.
        logging.info(f"Requisição de download manual de arquivos realizada.")
        logging.info(f">> PFJs: {str(pfjs)}")
        logging.info(f">> Prefixos: {str(prefixes)}")
        logging.info(f">> Extensões: {str(extensions)}")
        if date_type == "specific":
            logging.info(f">> Data Específica: {specific_date}")
            if prefixes and not extensions:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --prefix {" ".join(prefixes)} --date "{specific_date}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
            elif extensions and not prefixes:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --ext {" ".join(extensions)} --date "{specific_date}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
            elif not prefixes and not extensions:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --date "{specific_date}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
            elif prefixes and extensions:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --prefix {" ".join(prefixes)} --ext {" ".join(extensions)} --date "{specific_date}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
        elif date_type == "range":
            logging.info(f">> Período: {range_from} | {range_to}")
            if prefixes and not extensions:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --prefix {" ".join(prefixes)} --range "{range_from} {range_to}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
            elif extensions and not prefixes:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --ext {" ".join(extensions)} --range "{range_from} {range_to}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
            elif not prefixes and not extensions:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --range "{range_from} {range_to}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
            elif prefixes and extensions:
                run_command = f'python ../InputDataController/acquirer_file_downloader.py --acquirer "adyen" --pfj {" ".join(pfjs)} --prefix {" ".join(prefixes)} --ext {" ".join(extensions)} --range "{range_from} {range_to}" --ftpd "{ftpd}" --force' + ' --ftp "localhost eric 1234" --ftpd "/adyen"' if dev else ''
        subprocess.run(run_command, shell=True)

    return json.dumps({"result": "ok"})

Il programma che eseguo ha una vasta operazione di registrazione utilizzando il modulo di registrazione . Il fatto è che è abbastanza vitale per l'utente in primo piano vedere questo registro, poiché questo programma scarica file e carica i file su un FTP. Il problema è come funzionano le richieste. Avrei bisogno di eseguire un ciclo sul lato anteriore facendo richieste AJAX con parti del file di registro? Esiste un modo "stream" per inviare dati dal server al client in tempo reale? Non voglio implementare qualcosa di strano e inefficiente, quindi mi piacerebbe vedere alcuni suggerimenti. Cosa suggerisci?

    
posta Ericson Willians 16.11.2018 - 12:38
fonte

1 risposta

3

Puoi usare codifica di trasferimento chunked per rispondere in più frammenti. Ciò consente di trasmettere la risposta senza dover introdurre cambiamenti drastici. Tuttavia:

  • Ciò richiederà il supporto dal tuo framework web
  • Il tuo server sarà comunque bloccato fino al completamento della richiesta. Python ha anche una serie di framework web che possono utilizzare le funzioni di async di Python, come ad esempio http: //
  • Dovrai scrivere codice JavaScript lato client per aggiornare il tuo sito quando viene ricevuto il blocco successivo. JQuery non aiuterà qui.

Gli approcci alternativi sono:

  • Modella il registro come una risorsa esplicita a cui è possibile accedere tramite un URL, anche se questo registro potrebbe non essere ancora completo a un certo punto nel tempo. I clienti possono quindi interrogare la risorsa per vedere se è cambiata. Questo potrebbe essere più facile da implementare.

  • Utilizza i socket Web per inviare eventi al client. Tuttavia, è necessario disporre di un server compatibile con WebSpot.

In ogni caso, non utilizzare il modulo di registrazione per l'output visibile all'utente. Se qualche output è pensato per l'utente, modellalo esplicitamente.

    
risposta data 16.11.2018 - 13:52
fonte

Leggi altre domande sui tag