Скачать файл из API - PullRequest
       0

Скачать файл из API

0 голосов
/ 10 мая 2018

Я отправляю файл с веб-страницы на сервер Flask, затем выполняю некоторые преобразования на нем, а затем хочу вернуть преобразованный документ, чтобы пользователь мог его скачать. У меня есть одна кнопка, это отправит запрос POST:

fileUpload: function(file) {
  var formData = new FormData();
  formData.append('file',file);
  var xhr = new XMLHttpRequest();
  xhr.addEventListener("load", () => {
    console.log("asdf");
  });
  xhr.open("POST", "http://localhost:7733/receivedoc");
  xhr.send(formData);
}

Затем на сервере я выполняю преобразование и хочу вернуть файл:

...
#Transformations, save file to the file system
return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)

Однако в моем браузере нет файлов для загрузки. Ошибок нет, запрос вроде проходит ОК. Заголовки запроса:

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,hu;q=0.7,cs;q=0.6,sk;q=0.5,de;q=0.4
Connection: keep-alive
Content-Length: 114906
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycEQwQtGAXe1ysM9b
DNT: 1
Host: localhost:7733
Origin: http://localhost:5000
Referer: http://localhost:5000/

И полезная нагрузка запроса:

------WebKitFormBoundarycEQwQtGAXe1ysM9b
Content-Disposition: form-data; name="file"; filename="response.xls"
Content-Type: application/octet-stream


------WebKitFormBoundarycEQwQtGAXe1ysM9b--

response.xls - это именно тот файл, который я хочу скачать. Как я могу скачать его?

ОБНОВЛЕНИЕ - попытка реализовать решение Joost. Я делаю:

@app.route('/receivedoc', methods=['POST', 'GET', 'OPTIONS'])
@crossdomain(origin='*')
def upload_file():
    if request.method == 'POST':
#TRANSFORMING FILE, then saving below:
            writer = pd.ExcelWriter(filename)
            df_output.to_excel(writer,'Pacing', index=False)
            writer.save()
            return send_from_directory(directory=app.config['UPLOAD_FOLDER'], filename=filename)

    if request.method == 'GET':
        prefixed = [filename for filename in os.listdir(app.config['UPLOAD_FOLDER']) if filename.startswith("PG PEIT")]
        filename = max(prefixed)
        print("what what")
        return render_template_string('''<!DOCTYPE html>
            <html lang="en">
            <head>
            <meta charset="utf-8">
            <title>Your file is ready</title>
            </head>
            <body>
            <form enctype="multipart/form-data" method="post" name="fileinfo">
            <input type="text" name="fname" required />
            <input type="submit" value="request the file!" />
            </form>
            <script>
            function saveBlob(blob, fileName) {
                var a = document.createElement("a");
                a.href = window.URL.createObjectURL(blob);
                a.download = fileName;
                document.body.appendChild(a); // won't work in firefox otherwise
                a.click();
            }
            var form = document.forms.namedItem("fileinfo");
            form.addEventListener('submit', function(ev) {
            var oData = new FormData(form);
            var oReq = new XMLHttpRequest();
            oReq.responseType = 'blob';
            oReq.open("POST", "{{url_for('upload_file')}}", true);
            oReq.onload = function(oEvent) {
                if (oReq.status == 200) {
                var blob = oReq.response;
                var fileName = 'response.xml'
                saveBlob(blob, fileName);
                } else {
                alert("Error " + oReq.status + " occurred")
                }
            };
            oReq.send(oData);
            ev.preventDefault();
            }, false);
            </script>
            </body>
            </html>
            ''')

Это даст мне хороший ответ .html, но файл все равно не загрузится:

enter image description here

Что я не так понял?

1 Ответ

0 голосов
/ 11 мая 2018

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

Полностью функциональный пример:

from flask import Flask, render_template_string, request, url_for, send_from_directory


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        fname = request.form['fname']
        return send_from_directory('', fname, as_attachment=True)
    return render_template_string('''<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>title</title>
</head>
<body>
<form enctype="multipart/form-data" method="post" name="fileinfo">
  <input type="text" name="fname" required />
  <input type="submit" value="request the file!" />
</form>
<script>
function saveBlob(blob, fileName) {
    var a = document.createElement("a");
    a.href = window.URL.createObjectURL(blob);
    a.download = fileName;
    document.body.appendChild(a); // won't work in firefox otherwise
    a.click();
}

var form = document.forms.namedItem("fileinfo");
form.addEventListener('submit', function(ev) {
  var oData = new FormData(form);
  var oReq = new XMLHttpRequest();
  oReq.responseType = 'blob';
  oReq.open("POST", "{{url_for('index')}}", true);
  oReq.onload = function(oEvent) {
    if (oReq.status == 200) {
      var blob = oReq.response;
      var fileName = 'response.xml'
      saveBlob(blob, fileName);
    } else {
      alert("Error " + oReq.status + " occurred")
    }
  };
  oReq.send(oData);
  ev.preventDefault();
}, false);
</script>
</body>
</html>
''')


app.run()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...