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

如何用PHP Curl向CrossRef上传文件?遇405及401错误求助

CrossRef Deposit API 上传问题排查与解决

让我们一步步拆解你的问题,找到根本原因和对应的解决方案:

第一个错误:405 Method Not Allowed

你最初的代码犯了两个核心错误,导致服务器拒绝你的请求:

  • 请求格式不符合要求:CrossRef的Deposit API只接受multipart/form-data格式的表单提交,而你直接通过CURLOPT_INFILE上传XML内容,还手动设置了application/vnd.crossref.deposit+xml的Content-Type,这完全不符合API的预期。
  • 登录方式错误:你用CURLOPT_USERPWD做HTTP Basic认证,但CrossRef要求把登录信息作为表单字段(login_id和login_passwd)传递,而不是放在HTTP头里。

第二个错误:401 Unauthorized

修改后的表单上传代码依然没踩对API的要求:

  • 没有添加必填的表单字段:官方curl示例里的operation=doQueryUpload、login_id、login_passwd你都没放到POST参数里,服务器自然识别不到你的登录信息。
  • 旧版文件上传语法问题:PHP 5.5+已经弃用了@$filedata这种写法,应该用CURLFile类来处理文件上传,否则可能导致文件无法正确传递。
  • 手动设置Content-Type画蛇添足:curl会自动生成带正确boundary的multipart/form-data头,你手动设置反而会破坏这个格式,导致服务器解析表单失败。

正确的PHP CURL实现代码

下面是完全符合CrossRef官方要求的代码,包含所有必填项和正确的上传逻辑:

<?php
ini_set('display_errors', E_ALL);
define('CROSSREF_TEST_URL', 'https://test.crossref.org/servlet/deposit');

function depositToCrossRef($xmlFilePath) {
    // 先验证文件是否存在且可读
    if (!is_readable($xmlFilePath)) {
        return "错误:文件不存在或无法读取,请检查路径";
    }

    $curlCh = curl_init();

    // 配置基础CURL选项
    curl_setopt_array($curlCh, [
        CURLOPT_URL => CROSSREF_TEST_URL,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER => true, // 保留响应头方便调试
        CURLOPT_POST => true,
        // 不要手动设置Content-Type!curl会自动生成正确的multipart/form-data头
    ]);

    // 严格按照官方示例准备表单字段,字段名必须完全一致
    $postFields = [
        'operation' => 'doQueryUpload', // 必填操作标识
        'login_id' => '你的CrossRef用户名',
        'login_passwd' => '你的CrossRef密码',
        'fname' => new CURLFile(
            $xmlFilePath,
            'application/xml',
            basename($xmlFilePath)
        )
        // CURLFile自动处理文件类型和文件名,替代旧的@语法
    ];

    curl_setopt($curlCh, CURLOPT_POSTFIELDS, $postFields);

    // 执行请求并处理结果
    $response = curl_exec($curlCh);
    if ($response === false) {
        $errorMsg = curl_error($curlCh);
        curl_close($curlCh);
        return "CURL请求失败:" . $errorMsg;
    }

    // 获取HTTP状态码,CrossRef成功接收的状态码是303
    $httpCode = curl_getinfo($curlCh, CURLINFO_HTTP_CODE);
    curl_close($curlCh);

    if ($httpCode === 303) {
        return "Deposit提交成功!响应详情:\n" . $response;
    } else {
        return "提交失败,HTTP状态码:{$httpCode}\n响应详情:\n" . $response;
    }
}

// 调用函数,传入你的XML文件路径
echo depositToCrossRef(realpath('test.xml'));
?>

关键注意事项

  • 字段名严格匹配:operation、login_id、login_passwd、fname这四个字段是必填项,字段名必须和官方示例完全一致,大小写敏感。
  • 环境切换:测试用https://test.crossref.org/servlet/deposit,正式上线要换成https://doi.crossref.org/servlet/deposit。
  • 调试技巧:开启CURLOPT_HEADER => true可以查看完整的响应头和内容,方便你排查后续可能出现的问题。
  • PHP版本兼容:确保你的PHP版本在5.5及以上,CURLFile类才会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:11:58