You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP中通过CSRF令牌与Basic认证向Paperless NGX API上传文件

解决Paperless NGX文件上传的CSRF令牌获取及请求问题

问题根源

你当前使用/api/documents/post_document/这个仅接受POST请求的端点去发起GET请求获取CSRF令牌,因此触发了405 Method Not Allowed错误。Paperless NGX提供了专门的CSRF令牌获取方式,无需使用上传端点。

修正步骤

1. 正确获取CSRF令牌

Paperless NGX的API提供了专门的/api/csrf/端点用于获取CSRF令牌,该端点接受GET请求,直接返回包含令牌的JSON响应,同时响应头也会携带X-CSRFToken字段。

修正后的令牌获取函数:

function getCsrfToken($baseUrl, $username, $password) {
    $csrfUrl = rtrim($baseUrl, '/') . '/api/csrf/';
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $csrfUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
    curl_setopt($ch, CURLOPT_HEADER, true);

    $response = curl_exec($ch);
    $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $body = substr($response, $headerSize);
    curl_close($ch);

    // 优先从响应体提取令牌(更直接)
    $bodyData = json_decode($body, true);
    if (!empty($bodyData['csrfToken'])) {
        return $bodyData['csrfToken'];
    }

    // 备用:从响应头提取
    foreach (explode("\r\n", substr($response, 0, $headerSize)) as $line) {
        if (strpos($line, 'X-CSRFToken:') !== false) {
            list($key, $token) = explode(': ', $line);
            return trim($token);
        }
    }

    return null;
}

调用时传入Paperless的基础URL(而非上传端点):

$baseUrl = 'http://hostname:8000';
$csrfToken = getCsrfToken($baseUrl, $username, $password);

if (!$csrfToken) {
    die('CSRF-Token could not be retrieved');
}

2. 修正文件上传代码

上传部分存在两个关键问题:

  • 手动设置Content-Type: multipart/form-data会覆盖CURL自动生成的表单边界标识,导致Paperless无法解析上传数据,需移除该头信息。
  • 建议显式指定文件的MIME类型,避免自动检测错误。

修正后的上传函数:

function uploadFile($apiUrl, $filePath, $csrfToken, $username, $password) {
    $ch = curl_init();

    // 显式指定PDF的MIME类型,提升兼容性
    $file = new CURLFile($filePath, 'application/pdf', basename($filePath));

    $postData = [
        'document' => $file
        // 可选:添加Paperless支持的其他参数,比如文档标题、标签ID等
        // 'title' => 'Invoice 2024',
        // 'tags' => [1, 4]
    ];

    curl_setopt($ch, CURLOPT_URL, $apiUrl);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'X-CSRFToken: ' . $csrfToken,
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    // 调试用:失败时输出详细信息
    if ($httpCode !== 201) {
        echo 'HTTP状态码: ' . $httpCode . PHP_EOL;
        echo '响应内容: ' . $response . PHP_EOL;
        echo 'CURL错误: ' . curl_error($ch) . PHP_EOL;
    }

    curl_close($ch);

    if ($httpCode == 201) {
        echo 'File uploaded successfully!';
    } else {
        echo 'Error uploading file.';
    }
}

调用时传入正确的上传端点:

$apiUrl = rtrim($baseUrl, '/') . '/api/documents/post_document/';
uploadFile($apiUrl, $filePath, $csrfToken, $username, $password);

额外注意事项

  • 确保你的Paperless NGX实例启用了Basic认证,且当前用户拥有文档上传权限。
  • 若仍有问题,可查看Paperless的日志文件(通常位于/opt/paperless-ngx/logs/或容器日志),定位具体错误原因。
  • 确保PHP版本在5.5以上(支持CURLFile),推荐使用PHP 7.4及以上版本。

内容的提问来源于stack exchange,提问作者jlai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:17:06