Python / Flask - загрузка файла путем передачи пути из ноутбука Jupyter - PullRequest
0 голосов
/ 24 октября 2019

Контекст

Я создал приложение Flask, которое позволяет мне:

(1) загрузить файл GeoTIFF в указанную папку (UPLOAD_FOLDER)

(2) используйте GDAL, чтобы открыть загруженный GeoTIFF как фрейм данных Pandas, и вернуть JSON, содержащий все значения ячеек. Код приложения приведен ниже:

import os
import gdal
import numpy as np
import pandas as pd
import json
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename

UPLOAD_FOLDER = 'PATH_GOES_HERE'  #specify path
ALLOWED_EXTENSIONS = set(['tif'])

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return redirect(url_for('get_raster_data',
                                    filename=filename))
    return '''
    <!doctype html>
    <title>Upload raster file</title>
    <h1>Upload raster file</h1>
    <form method=post enctype=multipart/form-data>
      <input type=file name=file>
      <input type=submit value=Upload>
    </form>
    '''

@app.route('/rasterdata', methods=['GET'])
def get_raster_data():
    filename = secure_filename(request.args.get('filename'))
    try:
        if filename and allowed_file(filename):
            f = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            rast_data = gdal.Open(f)
            rast_array = np.array(rast_data.GetRasterBand(1).ReadAsArray())
        return pd.DataFrame(rast_array).to_json()
    except IOError:
        pass
    return "Unable to read file"

Приложение работает правильно (т.е. я тестировал с использованием локального хоста и работал в режиме отладки). Приложение позволяет мне открыть веб-страницу с помощью кнопок «Выбрать файл» и «Загрузить». После загрузки файла я перенаправляюсь на страницу «/ rasterdata» с ожидаемым выводом.

Мне было поручено создать Блокнот Jupyter, для которого пользователям в основном требуется только указать путь к GeoTIFF, который они хотели бы загрузить. Как только путь указан, приложение Flask должно запускаться и возвращать фрейм данных со всеми значениями ячеек GeoTIFF. Оттуда Блокнот проходит несколько этапов обработки, которые требуют ввода фрейма данных, но они не относятся к моему вопросу.

Вопрос

Как можноЯ загружаю файл в UPLOAD_FOLDER, просто указав путь к GeoTIFF в блокноте Jupyter? Ниже приведен код из моего ноутбука Jupyter. Я добавил комментарии, указывающие, где я застрял. Я подозреваю, что мне нужно будет изменить приложение Flask, чтобы оно указывало путь. Я не мог найти учебники для этого, хотя. Все учебники, которые я смог найти, дают мне код, похожий на тот, что у меня есть в настоящее время.

url = f'http://localhost:5000/upload'
my_path = r'C:\Users\admievan\Desktop\FlaskGDAL\my_raster.tif'

#Opening the upload page
with urllib.request.urlopen(path) as url:
    #THIS IS WHERE I AM STUCK
    #I want to pass my_path to the Flask application rather than having to
    #manually navigate to the file in the GUI interface that comes up when clicking
    #the "Choose file" button

#Reading the data web page as a panadas data frame
#This part works fine if 'my_raster.tif' is already in the UPLOAD_FOLDER
url = f'http://localhost:5000/rasterdata?filename=my_raster.tif'
df = pd.read_json(url, orient='rows')
df

1 Ответ

0 голосов
/ 24 октября 2019

Пакет запросов - ваш лучший друг, когда дело доходит до загрузки / извлечения и вызовов API. Каким бы ни был ваш хост для URL, вам нужно будет пройти через это. Загрузка не слишком сложна и может выглядеть примерно так:

import os
import base64
import urllib
import json
import requests
def jupyter_upload(token, filePath, resourceDstPath, jupyterUrl='http://localhost:8888'):
    dstPath = urllib.quote(resourceDstPath)
    dstUrl = '%s/api/contents/%s' % (jupyterUrl, dstPath)
    fileName = filePath[1 + filePath.rfind(os.sep):]
    headers = {}
    headers['Authorization'] = 'token '+token
    with open(filePath, 'r') as myfile:
        data=myfile.read()
        b64data=base64.encodestring(data)
        body = json.dumps({
            'content':b64data,
            'name': fileName,
            'path': resourceDstPath,
            'format': 'base64',
            'type':'file'
        })
        return requests.put(dstUrl, data=body, headers=headers, verify=True)`
...