使用 cURL 将文件发送到具有 XML 的 Web 服务会损坏该文件


Sending a file to a webservice with XML using cURL corrupts it

所以我有一些代码可以将职业申请发送到网络服务,然后将文件作为附件与表单中的其他元素一起通过电子邮件发送给人力资源部门。除文件外的所有部分都会根据需要通过电子邮件发送。文件上传到服务器而不会损坏。但是由此产生的电子邮件附件最终会损坏。

问题是;文件在到达 EOF 之前突然结束。假设它是一个pdf文件,当我在文本编辑器中打开原始文件和缩小大小的文件时,我看到开头是相同的,直到其中一个突然结束。其中一个大约是1MB,损坏的大约是600kB。

我尝试发送比生成的损坏文件更小(4kB(的文件,但该文件也以同样的方式损坏。生成的文件约为 1kB。

我得到的 xml 响应说:

<?xml version="1.0" encoding="utf-8"?><SENDEMLRSP><RTCD>1</RTCD><EXP>OK</EXP><RSP_LIST><RSP><MSGID>0</MSGID><EID /><RESULT>Invalid length for a Base-64 char array or string.</RESULT></RSP></RSP_LIST></SENDEMLRSP>

感兴趣的是这部分:

<RESULT>Invalid length for a Base-64 char array or string.</RESULT>

我准备了一个小表格,只有一个文件上传用于测试目的。

这是 HTML:

<html>
    <body>
    <form action="upload_file.php" method="post" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file"><br>
    <input type="submit" name="submit" value="Submit">
    </form>
    </body>
</html>

以下是相关的 PHP 代码:

if(isset($_FILES['file']['name']))  
            {
            echo ($_FILES['file']['name']);
            echo ($_FILES['file']['tmp_name']);
            $target = $_FILES['file']['name'];

            move_uploaded_file( $_FILES['file']['tmp_name'], $target);
            $rawdata = file_get_contents($target);
            $data = urldecode($rawdata);
            $data = base64_encode($rawdata);

            //error_log('uploadconvertscope');

            $iletisimrcpt = '<RCPT>
                           <TA>someemail@address.com</TA>
                           <MSG>kgsg</MSG>
                           <SBJ>'. strlen($rawdata).'</SBJ>
                           <OBOE>'.OBOE.'</OBOE>
                           <OBON>'.OBON.'</OBON>
                           <ATT_LIST><ATT><FN>'.$_FILES['file']['name'].'</FN><DATA>'.$data.'</DATA></ATT></ATT_LIST>
                  </RCPT>';

          $request = '<?xml version="1.0" encoding="utf-8"?>
               <SENDEML>
                   <VERSION>1.0</VERSION>
                   <TOKEN>'.$token.'</TOKEN>
                   <JID>'.JOBID.'</JID>
                   <MSG>Kariyar Basvuru isteði baþarýyla yerleþtirildi.</MSG>
                   <SBJ>Kariyar Basvuru</SBJ>
                   <RCPT_LIST>
                   '.$iletisimrcpt.'
                   </RCPT_LIST>
               </SENDEML>';
        error_log($request );
        $params = array('data' => $request);
        $response = processRequest(EML_URL, $params);
        error_log($response );
        $xml = new SimpleXmlElement($response);
        }

processRequest 函数与消息的其余部分一起工作。所以这可能不是问题,但这是代码:

<?php
        function processRequest($url, $params) {
        if(!is_array($params))
        return false;
        $post_params = "";
        foreach($params as $key => $val) {
        $post_params .= $post_params?"&":"";
        $post_params .= $key."=".$val;
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_VERBOSE, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 0);
        curl_setopt($ch, CURLOPT_HEADER, false); // 'true', for developer testing purpose
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params);
        $data = curl_exec($ch);
        if(curl_errno($ch))
        print curl_error($ch);
        else
        curl_close($ch);
        return $data;
        }
        ?>

当文件被读取为字符串时,看起来像 AHFAY3453GAW//长随机字符串//== 如果这意味着什么,它总是以两个"=="符号结尾。

我真的很困惑,因为文件可以使用此 C# 代码上传:

        byte[]  attach1 = File.ReadAllBytes(@"C:'Users'user'Downloads'amb.pdf");
        string attach = Convert.ToBase64String(attach1);
        EmlRequest.SetConnectionInformation("someapi.com", "admin", "password");
        EmlRequest eml=new EmlRequest(){  MessageJobId="DASFA1SDFAWEFA4X2==" };
        eml.Recipients.Add(new ApiEmlRecipient() { TargetAddress = "email@address.com" ,ToName="name",Message="xxx",Subject="subject"});
        eml.Recipients[0].Attachments.Add(new ApiEmlAttachment() { FileName = "abm.pdf", Data = attach });
        eml.Send();

这与它的PHP版本几乎相同。

我很久以前就想通了,但只是开始写一个答案。

所以问题是字符串中的"+"号被空格替换了。

这个位是负责的:

$rawdata = file_get_contents($target);
$data = urldecode($rawdata);
$data = base64_encode($rawdata);

我把它改成这样:

$rawdata = file_get_contents($_FILES['uploadedfile']['tmp_name']);
$data = base64_encode($rawdata);
$data = urlencode($data);

现在它起作用了。