多部分表单文件上传POST PHP cURL


Multipart form file upload POST PHP cURL

我想使用PHP和cURL通过http POST发送一个文件。

表单POST除了使用"application/json"发布的文件外,还可以处理基本字段。根据我的理解,这需要是多部分/形式的。

我得到的错误是线路
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 上的Notice: Array to string conversion

如果有人能帮忙那就太好了!

PHP

$orgID = (is_numeric($_POST['orgID']) ? (int)$_POST['orgID'] : 0);
$noteTitle = (isset($_POST['noteTitle']) ? $_POST['noteTitle'] : null);
$noteBody = (isset($_POST['noteBody']) ? $_POST['noteBody'] : null);
if(isset($_FILES['file']['tmp_name'])){
    $ch = curl_init();
    $cfile = new CURLFILE($_FILES['file']['tmp_name'], $_FILES['file']['type'], $_FILES['file']['name']);
    $data = array();                
    $data["TITLE"] = "$noteTitle";
    $data["BODY"] = "$noteBody";
    $data["LINK_SUBJECT_ID"] = "$orgID";
    $data["LINK_SUBJECT_TYPE"] = "Organisation";        
    $data['FILE_ATTACHMENTS']['FILE_NAME'] = $_FILES['file']['name'];
    $data['FILE_ATTACHMENTS']['CONTENT_TYPE'] = $_FILES['file']['type'];
    $data['FILE_ATTACHMENTS']['URL'] = $_FILES['file']['tmp_name'];
    $localFile = $_FILES['file']['tmp_name'];
    $fp = fopen($localFile, 'r');       
    $headers = array(
        "authorization: Basic xxx",
        "cache-control: no-cache",
        "content-type: multipart/form-data",
        "postman-token: xxx"
    );
    curl_setopt($ch, CURLOPT_URL, "https://api.insight.ly/v2.1/Notes");
    curl_setopt($ch, CURLOPT_UPLOAD, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
    curl_setopt($ch, CURLOPT_INFILE, $fp);
    curl_setopt($ch, CURLOPT_NOPROGRESS,false); 
    curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
    curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $response = curl_exec($ch);
    if ($response === true) {
        $msg = 'File uploaded successfully.';    
    }
    else {
        $msg = curl_error($ch);         
    }
    curl_close ($ch);
    $return = array('msg' => $msg);
    echo json_encode($return);
}

HTML

<form method="POST" action="formSend.php" enctype="multipart/form-data">
    <input type="text" value="" name="orgID">
    <input type="text" value="" name="noteTitle">
    <input type="text" value="" name="noteBody">  
    <input name="file" type="file" id="file"/>
    <input type="submit" value="Submit" name="btnUpload"/>
</form>

嗨,我已经解决了这个问题。

我的params在api端点上设置不正确。需要设置note_id(c_id)

但我现在面临的问题是一次发布所有数据。我在创建笔记后发布文件,从而为我生成用于发布文件的笔记id。有人能帮忙吗?我可以发布一个新问题。

请参阅下面的更新代码:

//$orgID = (is_numeric($_POST['orgID']) ? (int)$_POST['orgID'] : 0);
//$noteTitle = (isset($_POST['noteTitle']) ? $_POST['noteTitle'] : null);
//$noteBody = (isset($_POST['noteBody']) ? $_POST['noteBody'] : null);
$noteID = (isset($_POST['noteID']) ? $_POST['noteID'] : null);
$localFile = $_FILES['file']['tmp_name'];
$fp = fopen($localFile, 'r');
$curl = curl_init();
$cfile = new CURLFILE($_FILES['file']['tmp_name'], $_FILES['file']['type'], $_FILES['file']['name']);
$data = array();                
//$data["TITLE"] = "$noteTitle";
//$data["BODY"] = "$noteBody";
//$data["LINK_SUBJECT_ID"] = "$orgID";
//$data["LINK_SUBJECT_TYPE"] = "Organisation";        
$data['FILE_ATTACHMENTS'] = $cfile;
curl_setopt_array($curl, array(
  CURLOPT_UPLOAD => 1,
  CURLOPT_INFILE => $fp,
  CURLOPT_NOPROGRESS => false, 
  CURLOPT_BUFFERSIZE => 128,
  CURLOPT_INFILESIZE => filesize($localFile),
  CURLOPT_URL => "https://api.insight.ly/v2.1/Notes/?c_id=" . $noteID . "&filename=" . $_FILES['file']['name'],
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $data,      
  CURLOPT_HTTPHEADER => array(
    "authorization: Basic xxx",
    "cache-control: no-cache",
    "content-type: multipart/form-data",
    "postman-token: xxx"
  ),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

HTML

<form method="POST" action="formSend.php" enctype="multipart/form-data">
    //<input type="text" value="" name="orgID">
    //<input type="text" value="" name="noteTitle">
    //<input type="text" value="" name="noteBody"> 
    <input type="text" value="" name="noteID">
    <input name="file" type="file" id="file"/>
    <input type="submit" value="Submit" name="btnUpload"/>
</form>

如果有人感兴趣,这是我使用fpdf从web表单生成PDF文档的解决方案,然后自动发送,而不是上传文件。FPDF文件--->通过CURL自动发送,不与文件上传

您需要为要发布的数据构建查询字符串。使用http_build_query

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

我看到的一个遗漏是,您需要将$cfile对象添加到$data数组中。这一点,再加上萨米尔的回答,应该会让你们平分秋色。

这一切很快就会变得非常混乱和"矛盾"!由于cUrl非常灵活和强大,使用上下文中的微小差异会产生巨大影响,并可能导致长达数天的不存在的错误追踪。

其次,您发布到的URL/Endpoint也可以有自己的"实现"和期望。当经验只涉及GET请求并且假设/期望基于PHP Super Easy$_REQUEST 时,这种理解会变得复杂

在上面的例子中,简化:这是一个实际工作的例子,但postfields($post)已经从使用中的50多个减少到了几个。这将作为多部分表单数据发布。

这里的重要选项是使用CURLOPT_POST和CURLOPT_POSTFIELDS以及NOT CURLOPT_CUSTOMREQUEST的选项。这样做需要您处理所需的标头,特别是内容大小标头等。

// Post "field" array. Notice its 1 Dimensional. Else, this should rather accept JSON. simply decode array to json and proceed). Depends what server is expecting - Form data, Form + files, json or maybe just a RAW request body.
$post = array(  
            'RsmMaster1_TSM' => $tsm,
            '__EVENTTARGET' => '__Page',
            '__EVENTARGUMENT' => 'ExcelExport',
            '__VIEWSTATE'  => $viewstate,
            '__VIEWSTATEGENERATOR'  => $viewstategenerator,
            '__EVENTVALIDATION'  => $eventvalidation
 );
// Optional, Required in THIS case because, well gosh darn who knows, as the receiving server admin?
$headers = array(   
                'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language: en-ZA,en-GB;q=0.8,en-US;q=0.5,en;q=0.3',
                'Referer: https://example.com/Main.aspx'  
            );
// cUrl it into the goal!
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://example.com/Main.aspx');
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);                                                                  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7");
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');                                                                   
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);    
curl_setopt($ch, CURLOPT_HEADER, 0);
// curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); // Session maintain!
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FAILONERROR,    TRUE   );
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE  );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE  );
$content = curl_exec($ch);
curl_close($ch);