如何将 request.FILES 读入 Geodjango 中的 DataSource

问题描述

因此,我们的目标是创建一个网页以将 .shp 文件加载到其中并以 JsonResponse 的形式获取一些计算的摘要。我已经准备好计算和所有内容,当我向相关文件添加手动路径时,它运行良好。但是,目标是让其他人能够上传数据并获得响应,因此我无法对路径进行硬编码。

总体方法

  • 通过 forms.FileField() 和 request.FILES['file_name'] 读入。在此之后,我需要将此 request.FILES 对象传输到 DataSource 以便读取它。如果可能,我宁愿不将文件上传到 pc 上,而是直接从内存中工作。

forms.py

from django import forms
from django.core.files.storage import FileSystemStorage


class UploadFileForm(forms.Form):
    # title = forms.CharField(max_length=50)
    file = forms.FileField()

views.py

import json
import os

from django.http import Http404,HttpResponse,HttpResponseRedirect
from django.shortcuts import render

from django.template import loader
from django.contrib import messages
from django.views.generic import TemplateView
from django.http import JsonResponse

from django.conf import settings
from .forms import UploadFileForm
from . import models
from django.shortcuts import redirect
from gisapp.functions.functions import handle_uploaded_file,handle_uploaded_file_two
from django.contrib.gis.gdal import DataSource
from django.core.files.uploadedfile import UploadedFile,TemporaryUploadedFile
import geopandas as gpd
import fiona


def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST,request.FILES)
        if form.is_valid():
            f = request.FILES['file']
            # geo2 = gpd.read_file(f)
            # print(geo2)
            # f_path = os.path.abspath(os.path.join(os.path.dirname(f),f))

            # f_path = TemporaryUploadedFile.temporary_file_path(UploadedFile(f))
            # print(f_path)
            # f_path = f.temporary_file_path()
            # new_path =  request.FILES['file'].temporary_file_path
            # print(f'This is file path: {f_path}')
            # print(f'This is file path: {new_path}')
            # data = DataSource(f'gisapp/data/{f}') -- given an absolute path it works great
            data = DataSource(f) -- constantly failing
            # data = DataSource(new_path)
            # print(f'This is file path: {f_path}')
            layer = data[0]
            if layer.geom_type.name == "polygon" or layer.geom_type.name == "Linestring":
                handle_uploaded_file(request.FILES['file'])
            elif layer.geom_type.name == "Point":
                handle_uploaded_file_two(request.FILES['file'])

            return JsonResponse({"Count": f"{handle_uploaded_file_two(request.FILES['file'])[0]}","Bounding Box": f"{handle_uploaded_file_two(request.FILES['file'])[1]}"})
            
            # return JsonResponse({"Count": f"{handle_uploaded_file(request.FILES['file'])[0]}","Minimum": f"{handle_uploaded_file(request.FILES['file'])[1]}","Maximum": f"{handle_uploaded_file(request.FILES['file'])[1]}"})
            # instance = models.GeometryUpload(file_field=request.FILES['file'])
            # instance.save()
            # # return HttpResponseRedirect('/success/')
    else:
        form = UploadFileForm()
    return render(request,'upload.html',{'form': form})

我得到的错误

django.contrib.gis.gdal.error.GDalexception: Invalid data source input type: <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>

现在,正如您从views.py 中的upload_file() 中看到的,我尝试了多种操作,当我添加绝对路径时,它可以工作,但除此之外我似乎无法将文件上传到DataSource 所以我可以在以后的分析中使用它。

解决方法

Looking at how Django handles this,似乎无法处理内存文件。文件的路径被传递给 OGR 的 C API,然后它处理打开文件和读入文件。