curl을 사용하여 파일과 함께 POST 데이터 업로드


414

cURL을 사용하여 HTTP POST에서 데이터 매개 변수를 보낼뿐만 아니라 특정 양식 이름의 파일을 업로드하고 싶습니다. 어떻게해야합니까?

HTTP Post 매개 변수 :

userid = 12345 filecomment = 이미지 파일입니다

HTTP 파일 업로드 : 파일 위치 = /home/user1/Desktop/test.jpg 파일의 양식 이름 = 이미지 (PHP 측의 $ _FILES [ 'image']에 해당)

cURL 명령의 일부를 다음과 같이 생각했습니다.

curl -d "userid=1&filecomment=This is an image file" --data-binary @"/home/user1/Desktop/test.jpg" localhost/uploader.php

내가 얻는 문제는 다음과 같습니다.

Notice: Undefined index: image in /var/www/uploader.php

문제는 $ _FILES [ 'image']를 사용하여 PHP 스크립트에서 파일을 선택하는 것입니다.

cURL 명령을 적절하게 조정하려면 어떻게합니까?

답변:


656

-F옵션 을 사용해야합니다 .
-F/--form <name=content> Specify HTTP multipart POST data (H)

이 시도:

curl \
  -F "userid=1" \
  -F "filecomment=This is an image file" \
  -F "image=@/home/user1/Desktop/test.jpg" \
  localhost/uploader.php

1
파일을 URL 인코딩하는 것에 대해 혼란스러워합니다. JPG 및 PNG 파일을 아무런 문제없이 수정하지 않고 업로드했습니다.
Deanna Gelbart

1
@DavidGelbart 당신이 맞아요. 내 초기 답변 -d은 실수로 옵션을 참조 했으며 입력 URL로 인코딩해야합니다. -F옵션에 대한 답변을 업데이트했을 때 제거해야했습니다 . 찾아 주셔서 감사합니다.
jimp

3
@ user956424이 예에서 "image"를 필드 이름으로 설정하십시오. PHP와 같은 일부 언어는 그룹화해야하는 입력에 "image []"와 같은 것을 지정하면 배열을 작성합니다.
jimp

1
무엇 @인은 image=@/..?
티모

2
@Timo 명명 된 양식 필드의 내용이 파일 경로에서로드되어야 함을 의미합니다. 그것이 없으면 문자열 인수 자체가 전달됩니다.
날씬한

93

사용자 ID를 경로 변수로 캐치 (권장) :

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "data=@test.mp3" http://mysuperserver/media/1234/upload/

양식의 일부로 사용자 ID를 잡기 :

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "data=@test.mp3;userid=1234" http://mysuperserver/media/upload/

또는:

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "data=@test.mp3" -F "userid=1234" http://mysuperserver/media/upload/

16
-F 설정 필요 없음"Content-Type: multipart/form-data"
William Hu

10
표시된 세미콜론 구분 기호로 -F를 제대로 작동시킬 수 없습니다. 대신 두 개의 중복 -F 인수를 제공해야했습니다. 예 : -F "data=@test.mp3"-F "userid = 1234"
robbpriestley

22

여기 내 해결책이 있습니다. 많은 게시물을 읽었으며 실제로 도움이되었습니다. 마지막으로 cURL과 PHP를 사용하여 작은 파일에 대한 코드를 작성했는데 실제로 유용하다고 생각합니다.

public function postFile()
{    
        $file_url = "test.txt";  //here is the file route, in this case is on same directory but you can set URL too like "http://examplewebsite.com/test.txt"
        $eol = "\r\n"; //default line-break for mime type
        $BOUNDARY = md5(time()); //random boundaryid, is a separator for each param on my post curl function
        $BODY=""; //init my curl body
        $BODY.= '--'.$BOUNDARY. $eol; //start param header
        $BODY .= 'Content-Disposition: form-data; name="sometext"' . $eol . $eol; // last Content with 2 $eol, in this case is only 1 content.
        $BODY .= "Some Data" . $eol;//param data in this case is a simple post data and 1 $eol for the end of the data
        $BODY.= '--'.$BOUNDARY. $eol; // start 2nd param,
        $BODY.= 'Content-Disposition: form-data; name="somefile"; filename="test.txt"'. $eol ; //first Content data for post file, remember you only put 1 when you are going to add more Contents, and 2 on the last, to close the Content Instance
        $BODY.= 'Content-Type: application/octet-stream' . $eol; //Same before row
        $BODY.= 'Content-Transfer-Encoding: base64' . $eol . $eol; // we put the last Content and 2 $eol,
        $BODY.= chunk_split(base64_encode(file_get_contents($file_url))) . $eol; // we write the Base64 File Content and the $eol to finish the data,
        $BODY.= '--'.$BOUNDARY .'--' . $eol. $eol; // we close the param and the post width "--" and 2 $eol at the end of our boundary header.



        $ch = curl_init(); //init curl
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                         'X_PARAM_TOKEN : 71e2cb8b-42b7-4bf0-b2e8-53fbd2f578f9' //custom header for my api validation you can get it from $_SERVER["HTTP_X_PARAM_TOKEN"] variable
                         ,"Content-Type: multipart/form-data; boundary=".$BOUNDARY) //setting our mime type for make it work on $_FILE variable
                    );
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/1.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'); //setting our user agent
        curl_setopt($ch, CURLOPT_URL, "api.endpoint.post"); //setting our api post url
        curl_setopt($ch, CURLOPT_COOKIEJAR, $BOUNDARY.'.txt'); //saving cookies just in case we want
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // call return content
        curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); navigate the endpoint
        curl_setopt($ch, CURLOPT_POST, true); //set as post
        curl_setopt($ch, CURLOPT_POSTFIELDS, $BODY); // set our $BODY 


        $response = curl_exec($ch); // start curl navigation

     print_r($response); //print response

}

이것으로 우리는 다음과 같은 var가 게시 된 "api.endpoint.post"에 도착해야합니다. 이 스크립트를 사용하여 쉽게 테스트 할 수 postFile()있으며 마지막 행 의 함수에서이 디버그를 받아야합니다 .

print_r($response); //print response

public function getPostFile()
{

    echo "\n\n_SERVER\n";
    echo "<pre>";
    print_r($_SERVER['HTTP_X_PARAM_TOKEN']);
    echo "/<pre>";
    echo "_POST\n";
    echo "<pre>";
    print_r($_POST['sometext']);
    echo "/<pre>";
    echo "_FILES\n";
    echo "<pre>";
    print_r($_FILEST['somefile']);
    echo "/<pre>";
}

잘 작동해야하고 더 나은 솔루션 일 수는 있지만 이것이 작동하며 경계 및 다중 부분 / From-Data MIME이 PHP 및 cURL 라이브러리에서 작동하는 방식을 이해하는 데 실제로 도움이됩니다.


인코딩되지 않은 파일을 보내야 할 경우 $ BODY. = 'Content-Transfer-Encoding : multipart / form-data'줄을 변경하십시오. $ eol. $ eol; // 마지막 콘텐츠와 2 $ eol, $ BODY. = file_get_contents ($ file_url)을 넣습니다. $ eol; // Base64 File Content와 $ eol을 작성하여 데이터를 완성합니다.
andreah

8

CSV와 같은 이진 파일을 업로드하는 경우 아래 형식을 사용하여 파일을 업로드하십시오.

curl -X POST \
    'http://localhost:8080/workers' \
    -H 'authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyIsInR5cGUiOiJhY2Nlc3MifQ.eyJ1c2VySWQiOjEsImFjY291bnRJZCI6MSwiaWF0IjoxNTExMzMwMzg5LCJleHAiOjE1MTM5MjIzODksImF1ZCI6Imh0dHBzOi8veW91cmRvbWFpbi5jb20iLCJpc3MiOiJmZWF0aGVycyIsInN1YiI6ImFub255bW91cyJ9.HWk7qJ0uK6SEi8qSeeB6-TGslDlZOTpG51U6kVi8nYc' \
    -H 'content-type: application/x-www-form-urlencoded' \
    --data-binary '@/home/limitless/Downloads/iRoute Masters - Workers.csv'

4
이진 CSV 파일의 예를보고 싶습니다.
폴리스

4
@polis 옵션 --data-binary에 지시 curl없는 모든 데이터의 사전 처리를 할 수는 반대로 --data플래그. 의견을 직접 처리하려면 텍스트도 이진이지만 ASCII 문자로 해석 할 수 있습니다. 독특한 예를 원한다면 이모티콘이 포함 된 필드를 가진 CSV에 대해 생각해보십시오. 그들의 바이트는 텍스트에 직접 매핑되지 않습니다
Ciprian Tomoiagă

3

여기서 나를 이끌어 낸 문제는 기본 사용자 오류로 판명되었습니다 @. 파일 경로에 부호를 포함하지 않았 으므로 curl은 내용이 아닌 파일의 경로 / 이름을 게시하고있었습니다. 따라서 Content-Length값은 테스트 파일의 너비를 감안할 때 예상되는 479가 아닌 8이었습니다.

Content-Length컬이 파일을 읽고 게시물 때 헤더가 자동으로 계산됩니다.

curl -i -H "Content-Type: application/xml" --data "@test.xml" -v -X POST https://<url>/<uri/

... <내용 길이 : 479 ...

앞으로 다른 초보자를 돕기 위해 여기에 게시하십시오.


2

대안에 관해서는 curl, 당신은 사용할 수 있습니다 HTTPie 인간을위한 도구 컬-처럼, it'a의 CLI를.

  1. 설치 지침 : https://github.com/jakubroztocil/httpie#installation

  2. 그런 다음 다음을 실행하십시오.

    http -f POST http://localhost:4040/api/users username=johnsnow photo@images/avatar.jpg
    
    HTTP/1.1 200 OK
    Access-Control-Expose-Headers: X-Frontend
    Cache-control: no-store
    Connection: keep-alive
    Content-Encoding: gzip
    Content-Length: 89
    Content-Type: text/html; charset=windows-1251
    Date: Tue, 26 Jun 2018 11:11:55 GMT
    Pragma: no-cache
    Server: Apache
    Vary: Accept-Encoding
    X-Frontend: front623311
    
    ...

2

많은 시도 후에이 명령이 저에게 효과적이었습니다.

curl -v -F filename=image.jpg -F upload=@image.jpg http://localhost:8080/api/upload

1

다음은 업로드 된 파일의 임의 파일 이름을 올바르게 이스케이프 처리하는 방법입니다 bash.

#!/bin/bash
set -eu

f="$1"
f=${f//\\/\\\\}
f=${f//\"/\\\"}
f=${f//;/\\;}

curl --silent --form "uploaded=@\"$f\"" "$2"

0

이 명령으로 작동했습니다. curl -F 'filename=@/home/yourhomedirextory/file.txt' http://yourserver/upload

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.