PHP cURL文件上传到JSP脚本失败.通过浏览器上传的相同文件有效


PHP cURL file upload to JSP script fails. Same file uploaded via browser works

使用PHP/cURL登录网站并尝试上传文件。它返回错误消息,"错误:文件上传未处理。请确保选择指定模板格式的适用excel文件进行上传。"此错误与我从浏览器上传并给它一个错误格式的文件(如.jpg)时收到的消息不同。

如果我通过Firefox上传相同的excel文件,它就可以工作,并被服务器接受。

那么,我如何才能像使用Firefox那样通过PHP/cURL实现这一点呢?

我尝试了同样的上传到我自己的PHP脚本,它也很好。我在这里也复习了一些相关的问题,尝试了各种各样的东西,没有任何区别。我尝试了使用和不使用MIME类型,也尝试了使用或不使用选项CURLOPT_SSL_VERIFYPEER和CURLOPT_HTTPHEADER。

网站的所有者并没有特别的帮助,只是告诉我其他人正在做这件事

以下是我的代码:

$url = 'https://www.example.com/uploadController_u.jsp';
curl_setopt( $ch, CURLOPT_COOKIEJAR, $cookie_file );
curl_setopt( $ch, CURLOPT_COOKIEFILE, $cookie_file );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
curl_setopt( $ch, CURLOPT_MAXREDIRS, 10 );
curl_setopt( $ch, CURLOPT_FAILONERROR, true );
curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0");
curl_setopt( $ch, CURLOPT_REFERER, $curl_referer );
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_VERBOSE, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 ); // Added based on another StackOverflow question
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Expect:') ); // Added based on another StackOverflow question
// Tried with and without the MIME type
$post_vars = array( 
'file' => "@/home/someuser/private/eapis-test/mx/Template-test.xls;type=application/vnd.ms-excel",
'submit' => 'Upload file'  );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_vars );
$response = curl_exec( $ch );

下面是我发布到的表单。我在javascript中没有找到任何对form1的引用。

<table border="0"  cellspacing="0" cellpadding="0">
    <form action="uploadController_u.jsp" method="post" enctype="multipart/form-data" name="form1" id="form1">
    <tr>
        <td align="left">
            <p>
                <h2>Upload Flight:</h2>
            </p>
        </td>
    </tr>
    <tr>
        <td>
            <b style="font-size: 90%;">To add a new flight from spreadsheet, </b>
        </td>
        <td align="left">
            <input name="file" type="file" id="file" align="left" size="36">
        <td>
    </tr>
    <tr>
        <td>
        </td>
        <td align="left">
            <p>
                <input type="submit" name="Submit" value="Upload file"/>
            </p>
        </td>
    </tr>
    </form>
</table>

我尝试了这些标题来更好地模拟浏览器,但没有用:

$header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
$header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
$header[] = "Cache-Control: max-age=0";
$header[] = "Connection: keep-alive";
$header[] = "Keep-Alive: 300";
$header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
$header[] = "Accept-Language: en-us,en;q=0.5";
$header[] = "Pragma: ";
curl_setopt( $ch, CURLOPT_HTTPHEADER, $header ); 

"请确保选择指定模板格式的适用excel文件进行上传"

可能与你的剧本无关。如果目标服务器说的是实话,那么您上传的文件不是"指定的模板格式"。

如果是,并且你绝对确定是,那么错误消息是不正确的,唯一明智的做法是再次联系服务器管理员。

不是真正的解决方案,因为您的所有代码似乎都是正确的,但关于如何在没有服务器管理员帮助的情况下进行故障排除的一些建议。

  1. 自己创建一个简单的上传脚本,并使用脚本将文件发布到自己的服务器。仔细检查您收到的文件是否与您发送的文件100%相等。

  2. 尽管您的内容类型是正确的,但请尝试使用application/octet-stream或什么都不使用,看看这是否会改变

  3. 如果您还没有,请尝试运行本地php服务器来运行curl脚本,以确保没有影响错误的IP检查。

  4. 由于当JPG的文件类型错误时,您会收到不同的错误,请尝试将JPG与脚本一起上传,看看是否会收到相同的错误。如果您遇到与excel文件相同的错误,则很可能是服务器端的安全检查。

  5. 使用像BURP套件这样的工具来检查正在发送的实际标头等,并尝试用curl来模拟它们。Firebug可能也能工作,但就我个人而言,当我陷入困境时,我更喜欢Burp:)

由于您声明脚本在您自己的网站上运行良好,并且我在代码中没有看到任何错误,我猜测您可能没有发送足够的数据或正确的数据。

当我制作yahoo.com登录脚本时,我使用Firefox的Tamper Data作为代理,查看浏览器发送到特定网页的所有数据,看看是否有一些你不知道的发送数据。

此外,我会尝试从浏览器中删除一些特定功能,如cookie或删除要上传的refer和string,以准确了解是什么错误/缺失导致了"错误:文件上传未处理。请确保选择指定模板格式的适用excel文件进行上传。"错误。

我通常使用HackBar(Firefox)来删除推荐人和Web开发人员工具栏来禁用Cookie、Javascript。。。

<?php
    $target_url = 'http://127.0.0.1/file.php';
        $file_name_with_full_path = realpath('./sample.jpeg');
        $post = array('extra' => '123456','file'=>'@'.$file_name_with_full_path);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,$target_url);
        curl_setopt($ch, CURLOPT_POST,1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        $result=curl_exec ($ch);
        curl_close ($ch);
        echo $result;
?>