通过 API 接收一个远程文件 URL,然后服务器从该 URL 下载文件,再将其转换为 PDF,并将前两页转换为图片,最终上传到 阿里云 OSS。这里不再是通过文件上传的方式,而是通过提交远程 URL 地址。
调整后的解决方案
我们将修改之前的 Flask API,让它接受 远程文件 URL 作为输入。
依赖库安装
首先,确保安装以下所需的依赖:
pip install flask requests pdf2image oss2 python-docx
sudo yum install libreoffice poppler-utils
完整示例代码
from flask import Flask, request, jsonify
import os
import shutil
import requests
import subprocess
from pdf2image import convert_from_path
import oss2
# Flask 应用实例
app = Flask(__name__)
UPLOAD_FOLDER = '/tmp'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# 阿里云 OSS 配置
ACCESS_KEY_ID = 'your_access_key_id'
ACCESS_KEY_SECRET = 'your_access_key_secret'
BUCKET_NAME = 'your_bucket_name'
ENDPOINT = 'your_endpoint'
bucket = oss2.Bucket(oss2.Auth(ACCESS_KEY_ID, ACCESS_KEY_SECRET), ENDPOINT, BUCKET_NAME)
# 允许上传的文件扩展名
ALLOWED_EXTENSIONS = {'pdf', 'docx', 'txt', 'pptx'}
def allowed_file(filename):
    """检查文件是否是允许的格式"""
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def download_file(url):
    """从远程 URL 下载文件"""
    local_filename = os.path.join(UPLOAD_FOLDER, url.split("/")[-1])
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        with open(local_filename, 'wb') as f:
            f.write(response.content)
        return local_filename
    return None
def convert_to_pdf(input_file):
    """使用 LibreOffice 将文件转换为 PDF"""
    output_file = os.path.splitext(input_file)[0] + '.pdf'
    command = f'libreoffice --headless --convert-to pdf "{input_file}" --outdir {UPLOAD_FOLDER}'
    subprocess.run(command, shell=True)
    pdf_file = os.path.join(UPLOAD_FOLDER, os.path.basename(output_file))
    if os.path.exists(pdf_file):
        return pdf_file
    return None
def pdf_to_images(pdf_path):
    """将 PDF 前两页转换为图片"""
    images = convert_from_path(pdf_path, first_page=1, last_page=2)
    image_paths = []
    for i, image in enumerate(images):
        image_path = os.path.join(UPLOAD_FOLDER, f'page_{i + 1}.png')
        image.save(image_path, 'PNG')
        image_paths.append(image_path)
    return image_paths
def upload_to_oss(file_path):
    """上传文件到阿里云 OSS"""
    filename = os.path.basename(file_path)
    oss_path = f'uploads/{filename}'
    bucket.put_object_from_file(oss_path, file_path)
    return f'https://{BUCKET_NAME}.{ENDPOINT}/{oss_path}'
def cleanup_temp_files(*file_paths):
    """删除临时文件"""
    for file_path in file_paths:
        if os.path.exists(file_path):
            os.remove(file_path)
@app.route('/upload', methods=['POST'])
def upload_file():
    """处理上传 URL 请求"""
    file_url = request.form.get('url')
    if not file_url:
        return jsonify({'code': 1, 'message': '未提供 URL'}), 400
    # 从 URL 下载文件
    local_file = download_file(file_url)
    if not local_file or not allowed_file(local_file):
        return jsonify({'code': 1, 'message': '文件下载失败或文件类型不支持'}), 400
    try:
        # 1. 判断文件类型并转换为 PDF
        if local_file.endswith('.pdf'):
            pdf_file = local_file
        else:
            pdf_file = convert_to_pdf(local_file)
            if not pdf_file:
                return jsonify({'code': 1, 'message': '文件转换为 PDF 失败'}), 500
        # 2. 转换 PDF 前两页为图片
        image_paths = pdf_to_images(pdf_file)
        # 3. 上传 PDF 和图片到 OSS
        pdf_url = upload_to_oss(pdf_file)
        image_urls = [upload_to_oss(img) for img in image_paths]
        # 4. 返回结果
        return jsonify({
            'code': 0,
            'data': {
                'pdfurl': pdf_url,
                'views': image_urls
            }
        })
    finally:
        # 5. 清理临时文件
        cleanup_temp_files(local_file, pdf_file, *image_paths)
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
代码说明
- Flask 接口: - POST /upload:接收一个包含远程 URL 的请求。
- 检查文件是否可以从 URL 下载并保存到本地。
 
- 文件下载与处理: - 从 URL 下载文件到服务器。
- 如果文件是非 PDF 格式,则使用 LibreOffice将其转换为 PDF。
- 使用 pdf2image将 PDF 的前两页转换为 PNG 图片。
 
- 阿里云 OSS 上传: - 上传 PDF 和图片到 OSS,并返回 URL。
 
- 清理临时文件: - 上传完成后,自动删除服务器上的临时文件。
 
使用示例
使用 curl 命令进行测试:
curl --request POST \
  --url http://localhost:5000/upload \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data 'url=http://qiye.dev.udwz.cn/123.docx'
示例响应
{
  "code": 0,
  "data": {
    "pdfurl": "https://your_bucket.your_endpoint/uploads/123.pdf",
    "views": [
      "https://your_bucket.your_endpoint/uploads/page_1.png",
      "https://your_bucket.your_endpoint/uploads/page_2.png"
    ]
  }
}
注意事项
- 确保替换阿里云 OSS 的配置信息(ACCESS_KEY_ID,ACCESS_KEY_SECRET,BUCKET_NAME,ENDPOINT)。
- 确保 LibreOffice和poppler-utils已正确安装,以支持文档转换。
- 请确保服务器 /tmp目录有写入权限。
{"code":0,"data":{"pdfurl":"https://orangerescue2022.oss-cn-hangzhou.aliyuncs.com/pdf/123-d60becd4-1de5-4ed0-9ec3-0b3972b781f2.pdf","views":["https://orangerescue2022.oss-cn-hangzhou.aliyuncs.com/pdf/9f09ceb9-8ff0-4ad2-9030-771dc0cd86fc.png","https://orangerescue2022.oss-cn-hangzhou.aliyuncs.com/pdf/a7cb30b9-fe72-4e44-949d-f6a7b5352052.png"]}}