大多数PDF软件阅读服务是免费的,但是如果你想编辑一个PDF文档,比如从一个PDF文档中提取指定页面,合并多个PDF页面或者实现PDF页面的替换,你一般需要购买收费软件才可以。这当然难不倒程序员们,尤其Python程序员们。今天小编我就带你利用Django+PyPDF2开发一个比较实用的小APP,实现PDF页面在线提取, 页面合并与页面替换。文尾我们会附上GitHub源码地址。
项目开发总体思路
对于PDF页面提取,我们的开发思路是这样子的。我们设计一个表单,让用户上传一个PDF文件并输入提取页面号码。服务器在收到PDF文件后使用PyPDF2读取用户上传的PDF文件,提取我们所需要的页面,然后通过FileResponse将这个提取的PDF页面通过浏览器返回给客户。如果用户输入的是1,3,5,7这种页码,我们将逐一提取页面,将所有提取页面压缩成一个zip包返回给用户。
对于PDF合并,我们只需用户一次上传PDF文件即可。对于PDF替换,我们需要用户上传替换页,被替换的PDF文件及被替换页面号码。
这个应用很简单,并不需要建立什么模型Models。重点要编写的是视图views.py, 用来处理用户的请求。我们预计需要4个urls和4个对应的处理方法。
-
PDF单页提取(如1, 3, 5): pdf_single_page_extract
-
PDF按页面范围连续提取(如2-8): pdf_range_extract
-
PDF文件合并: pdf_merge
-
PDF文件替换: pdf_replace
本例需要安装如下两个Python库, 其中PyPDF2库将负责PDF文件读取, 分割和合并工作。
Django==2.1.3 PyPDF2==1.26.0
项目设置
使用django-admin startproject mypdfproject创建一个名叫mypdfproject的项目,然后进入该目录再使用python manage.py startapp pdf创建一个叫pdf的app,然后把这个app加入到你的mypdfproject/settings.py里INSTALLED_APPS去。
#mypdfproject/settings.py
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.staticfiles', 'pdf', ]
因为我们上传的PDF文件会临时存放在media文件夹,所以请在mypdfproject目录下建一个media文件夹,并在settings.py文件里设置为MEDIA_ROOT。我们还会用到css文件来美化网页,所以也请中设置好静态文件的STATIC_URL和STATIC_ROOT.
#mypdfproject/settings.py
STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') # 设置媒体文件夹, 对于图片和文件上传很重要 MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
同时别忘了了把我们app的urls也加到项目的urls.py里去。别忘了结尾的+static哦,否则媒体文件无法正确显示。
#mypdfproject/urls.py
from django.contrib import admin from django.urls import path, include # 对于显示静态文件非常重要 from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('pdf/', include('pdf.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
URLConf配置与表单
在pdf文件目录下创建一个urls.py, 添加如下代码。一共有4个urls, 分别对应PDF单页提取,PDF按页面范围连续提取, PDF合并与PDF替换。
# pdf/urls.py
from django.urls import path, re_path from . import views # namespace app_name = 'pdf' urlpatterns = [ # 上传pdf,用户输入需要提取的页面, 返回需要提取的页面 path('extract/single/', views.pdf_single_page_extract, name='pdf_single_page_extract'), path('extract/range/', views.pdf_range_extract, name='pdf_range_extract'), path('merge/', views.pdf_merge, name='pdf_merge'), path('replace/', views.pdf_replace, name='pdf_replace'), ]
另外我们还需要定义一些表单供用户上传PDF文件和输入页码,这些表单我们视图里会用到。
#pdf/forms.py
from django import forms class PdfExtractForm(forms.Form): file = forms.FileField(label="Upload PDF Document") page = forms.CharField(max_length=20, label="Page Number") def clean_file(self): file = self.cleaned_data.get('file') if not file.name.lower().endswith('.pdf'): raise forms.ValidationError("Only pdf documents are allowed. ") return file class PdfMergeForm(forms.Form): file1 = forms.FileField(label="PDF file 1") file2 = forms.FileField(label="PDF file 2", required=False) file3 = forms.FileField(label="PDF file 3", required=False) file4 = forms.FileField(label&#