#!/bin/bash # PaddleOCR Document Parser Script # Supports both sync and async modes set -e # Default values file_type="image" output_file="" verbose="false" async_mode="false" # Function to display usage usage() { cat << EOF Usage: $0 [OPTIONS] INPUT_FILE_PATH_OR_URL Parse documents using PaddleOCR API OPTIONS: -t, --type TYPE File type (image, pdf) [default: image] -o, --output FILE Output file [default: stdout] -v, --verbose Verbose output --async Use async mode (for large files/PDFs) -h, --help Show this help message ENVIRONMENT: PADDLEOCR_ACCESS_TOKEN Required: API access token PADDLEOCR_API_URL Required: Sync mode endpoint URL PADDLEOCR_JOB_URL Required for async: Async endpoint URL PADDLEOCR_MODEL Optional: Model name [default: PaddleOCR-VL-1.5] SETUP: 1. Visit https://www.paddleocr.com to get API credentials 2. Set environment variables: export PADDLEOCR_ACCESS_TOKEN="your_token" export PADDLEOCR_API_URL="https://your-endpoint/layout-parsing" EXAMPLES: # Sync mode (default) $0 document.jpg $0 -t pdf document.pdf $0 -o result.json document.jpg # Async mode (for large files) $0 --async large-document.pdf EOF } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -t|--type) file_type="$2" shift 2 ;; -o|--output) output_file="$2" shift 2 ;; -v|--verbose) verbose="true" shift ;; --async) async_mode="true" shift ;; -h|--help) usage exit 0 ;; -*) echo "Unknown option: $1" usage exit 1 ;; *) input_file="$1" shift ;; esac done # Validate input if [[ -z "$input_file" ]]; then echo "Error: Input file path or URL is required" usage exit 1 fi # Check required environment variables if [[ -z "$PADDLEOCR_ACCESS_TOKEN" ]]; then echo "Error: PADDLEOCR_ACCESS_TOKEN environment variable is required" echo "Get it from: https://www.paddleocr.com" exit 1 fi if [[ -z "$PADDLEOCR_API_URL" ]]; then echo "Error: PADDLEOCR_API_URL environment variable is required" echo "Set it to your PaddleOCR API endpoint" echo "Example: export PADDLEOCR_API_URL=\"https://your-endpoint.aistudio-app.com/layout-parsing\"" exit 1 fi # Set optional defaults PADDLEOCR_MODEL="${PADDLEOCR_MODEL:-PaddleOCR-VL-1.5}" # Check if input is a URL or local file if [[ "$input_file" =~ ^https?:// ]]; then is_url="true" if [[ "$verbose" == "true" ]]; then echo "Input is a URL: $input_file" >&2 fi else is_url="false" if [[ ! -f "$input_file" ]]; then echo "Error: Input file not found: $input_file" exit 1 fi if [[ "$verbose" == "true" ]]; then echo "Input is a local file: $input_file" >&2 fi fi # Use Python script for async mode if [[ "$async_mode" == "true" ]]; then if [[ -z "$PADDLEOCR_JOB_URL" ]]; then echo "Error: PADDLEOCR_JOB_URL environment variable is required for async mode" echo "Example: export PADDLEOCR_JOB_URL=\"https://your-endpoint.aistudio-app.com/api/v2/ocr/jobs\"" exit 1 fi if [[ "$verbose" == "true" ]]; then echo "Using async mode with model: $PADDLEOCR_MODEL" >&2 fi # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Run Python async parser if [[ -n "$output_file" ]]; then python3 "$SCRIPT_DIR/paddleocr_parse.py" --async-mode -o "$output_file" "$input_file" else python3 "$SCRIPT_DIR/paddleocr_parse.py" --async-mode "$input_file" fi exit 0 fi # Sync mode (bash implementation) # Validate file type case "$file_type" in image|img) file_type_code=1 ;; pdf) file_type_code=0 ;; *) echo "Error: Invalid file type '$file_type'. Supported: image, pdf" exit 1 ;; esac # Build payload - directly use URL or encode file if [[ "$is_url" == "true" ]]; then # Use URL directly in payload payload=$(cat <&2 fi else # Encode local file to base64 if [[ "$verbose" == "true" ]]; then echo "Encoding $input_file to base64..." >&2 fi file_base64=$(cat "$input_file" | base64 | tr -d '\n') payload=$(cat <&2 echo "Payload size: ${#payload} bytes" >&2 fi # Make API request # Use temporary file to avoid "Argument list too long" error for large payloads payload_file=$(mktemp) echo "$payload" > "$payload_file" if [[ "$verbose" == "true" ]]; then echo "Request payload saved to temporary file: $payload_file" >&2 fi # Use trap to ensure temporary file cleanup on script exit cleanup() { if [[ -f "$payload_file" ]]; then rm -f "$payload_file" if [[ "$verbose" == "true" ]]; then echo "Cleaned up temporary file: $payload_file" >&2 fi fi } trap cleanup EXIT response=$(curl -s -X POST "$PADDLEOCR_API_URL" \ -m 600 \ --fail-with-body \ -H "Authorization: token $PADDLEOCR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d @"$payload_file") # Check for curl errors curl_exit_code=$? if [[ $curl_exit_code -ne 0 ]]; then echo "Error: Curl request failed with code $curl_exit_code" exit 1 fi # Check response for errors using jq if ! echo "$response" | jq -e . >/dev/null 2>&1; then echo "Error: Invalid JSON response from API" exit 1 fi error_code=$(echo "$response" | jq -r '.errorCode // empty') error_msg=$(echo "$response" | jq -r '.errorMsg // empty') if [[ -n "$error_code" && "$error_code" != "0" ]]; then echo "API Error ($error_code): $error_msg" exit 1 fi # Extract and process result if [[ -n "$output_file" ]]; then echo "$response" > "$output_file" if [[ "$verbose" == "true" ]]; then echo "Output saved to: $output_file" >&2 fi else echo "$response" fi if [[ "$verbose" == "true" ]]; then echo "Processing completed successfully" >&2 fi