【问题标题】:Python/Flask - Uploading a file by passing a path from a Jupyter NotebookPython/Flask - 通过从 Jupyter Notebook 传递路径来上传文件
【发布时间】:2019-10-24 15:39:30
【问题描述】:

上下文

我创建了一个 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 Notebook,基本上只需要用户指定他们想要上传的 GeoTIFF 的路径。指定路径后,Flask 应用程序需要运行并返回所有 GeoTIFF 单元格值的数据框。从那里开始,Notebook 经历了一些需要数据框作为输入的处理步骤,但这些与我的问题无关。

问题

如何通过简单地在 Jupyter Notebook 中指定 GeoTIFF 的路径来将文件上传到 UPLOAD_FOLDER?下面是我的 Jupyter Notebook 中的代码。我添加了 cmets 指定我卡在哪里。我怀疑我需要修改 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

【问题讨论】:

    标签: python flask jupyter-notebook gdal geotiff


    【解决方案1】:

    在处理上传/提取和 API 调用时,请求包是您最好的朋友。 无论您的主机是什么网址,您都需要通过它。 上传并不太难,可能看起来像这样:

    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)`
    

    【讨论】:

    • 谢谢。这段代码应该放在烧瓶应用程序还是 Jupyter 笔记本中?我也不明白 token 参数。有必要吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 2013-08-30
    相关资源
    最近更新 更多