Django上传PDF提取图片文本报TypeError,求解决方案
Django文件上传与PDF图片文本提取问题
问题详情
开发的Django应用包含文件上传功能和展示文件内容的textarea:上传文本文件时内容可正常显示,但集成PDF图片文本提取功能时出现如下错误:
TypeError at /
image must be a wand.image.Image instance, not <UploadFile: UploadFile object (45)>
即使传入硬编码的PDF路径字符串,错误依然存在。尝试修改为pdfFile = wi(filename= uploadfile.image.path , resolution=300)仍未解决。
原视图代码
from django.shortcuts import render from django.views import View from django.http import HttpResponseRedirect from .forms import ProfileForm from .models import UploadFile from .textFromImages import TextFromImage from wand.image import Image as wi from PIL import Image import pytesseract from django.conf import settings import io import os class ReadingFile(View): def get(self, request): form = ProfileForm() return render(request, "main/create_profile.html", { "form": form }) def post(self, request): submitted_form = ProfileForm(request.POST, request.FILES) content = '' if submitted_form.is_valid(): uploadfile = UploadFile(image=request.FILES["upload_file"]) name_of_file = str(request.FILES['upload_file']) uploadfile.save() with open(os.path.join(settings.MEDIA_ROOT, f"{uploadfile.image}"), 'r') as f: print("Now its type is ", type(name_of_file)) # reading PDF file if name_of_file.endswith('.pdf'): pdfFile = wi(uploadfile, resolution=300) text_factuur_verdi = [] image = pdfFile.convert('jpeg') imageBlobs = [] for img in image.sequence: imgPage = wi(image=img) imageBlobs.append(imgPage.make_blob('jpeg')) for imgBlob in imageBlobs: image = Image.open(io.BytesIO(imgBlob)) text = pytesseract.image_to_string(image, lang='eng') text_factuur_verdi.append(text) return text_factuur_verdi # ENDING Reading pdf file else: content = f.read() print(content) return render(request, "main/create_profile.html", { 'form': ProfileForm(), "content": content }) return render(request, "main/create_profile.html", { "form": submitted_form, })
原HTML代码
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Create a Profile</title> <link rel="stylesheet" href="{% static "main/styles/styles.css" %}"> </head> <body> <form action="/" method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ form }} <button type="submit">Upload!</button> </form> {% if content %} <textarea name="" id="" cols="30" rows="10">{{content}}</textarea> {% endif %} </body> </html>
问题修正点
- 错误传入模型实例给wand.image.Image:
wi()不能直接接收UploadFile模型实例,需传入正确的文件路径或文件对象。 - 错误的文件打开模式:PDF是二进制文件,不能用文本模式
'r'打开;且处理PDF时无需打开文件,直接使用文件路径即可。 - 错误的返回值类型:处理PDF后直接返回列表
text_factuur_verdi会导致Django视图错误,需将列表拼接为字符串传给模板。 - 逻辑块嵌套错误:PDF处理代码不应放在
with open块内,避免不必要的文件操作。
修正后的视图代码
from django.shortcuts import render from django.views import View from .forms import ProfileForm from .models import UploadFile from wand.image import Image as wi from PIL import Image import pytesseract from django.conf import settings import io import os class ReadingFile(View): def get(self, request): form = ProfileForm() return render(request, "main/create_profile.html", {"form": form}) def post(self, request): submitted_form = ProfileForm(request.POST, request.FILES) content = '' if submitted_form.is_valid(): uploadfile = UploadFile(image=request.FILES["upload_file"]) name_of_file = str(request.FILES['upload_file']) uploadfile.save() # 获取上传文件的完整路径 file_path = os.path.join(settings.MEDIA_ROOT, str(uploadfile.image)) # 处理PDF文件 if name_of_file.endswith('.pdf'): text_factuur_verdi = [] # 使用filename参数传入PDF路径 with wi(filename=file_path, resolution=300) as pdfFile: image = pdfFile.convert('jpeg') imageBlobs = [] for img in image.sequence: imgPage = wi(image=img) imageBlobs.append(imgPage.make_blob('jpeg')) for imgBlob in imageBlobs: image = Image.open(io.BytesIO(imgBlob)) text = pytesseract.image_to_string(image, lang='eng') text_factuur_verdi.append(text) # 将列表拼接为字符串,用于在textarea显示 content = '\n\n'.join(text_factuur_verdi) # 处理文本文件 else: # 文本文件用'r'模式打开,指定编码避免乱码 with open(file_path, 'r', encoding='utf-8') as f: content = f.read() return render(request, "main/create_profile.html", { 'form': ProfileForm(), "content": content }) # 表单验证失败时返回原表单 return render(request, "main/create_profile.html", { "form": submitted_form, })
内容的提问来源于stack exchange,提问作者mightycode Newton
相关产品推荐
相关产品推荐

