POST verilerini dosyalarla yüklemek için curl kullanma


414

Ben sadece HTTP POST veri parametreleri göndermek için değil, aynı zamanda belirli form adı olan dosyaları yüklemek için cURL kullanmak istiyorum. Bunu nasıl yapmalıyım?

HTTP Post parametreleri:

userid = 12345 filecomment = Bu bir görüntü dosyası

HTTP Dosya yükleme: Dosya konumu = /home/user1/Desktop/test.jpg Dosya için form adı = image (PHP tarafındaki $ _FILES ['image'] ifadesine karşılık gelir)

CURL komutunun bir kısmını aşağıdaki gibi anladım:

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

Ben alıyorum sorun aşağıdaki gibidir:

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

Sorun ben PHP komut dosyasında dosyaları almak için $ _FILES ['image'] kullanıyorum.

CURL komutlarımı buna göre nasıl ayarlayabilirim?

Yanıtlar:


656

-FSeçeneği kullanmanız gerekir :
-F/--form <name=content> Specify HTTP multipart POST data (H)

Bunu dene:

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

1
Dosyanın url kodlamasıyla ilgili bölümden kafam karıştı. Bu tür JPG ve PNG dosyalarını değiştirmeden, herhangi bir sorun olmadan yükledim.
Deanna Gelbart

1
@DavidGelbart Haklısın. İlk cevabım -d, URL ile kodlanmış giriş gerektiren isteğe yanlışlıkla başvurdu . -FSeçeneğin cevabını güncellediğimde bunu kaldırmış olmalıydım . Yakaladığınız için teşekkürler.
jimp

3
@ user956424 Örnekte, "image" alanını alanınızın adına ayarlayın. Ve birlikte gruplanması gereken girdiler için "image []" gibi bir şey belirtirseniz, PHP gibi bazı diller bir dizi oluşturur.
jimp

1
Nedir @içinde image=@/..?
Timo

2
@Timo Adlandırılmış form alanının içeriğinin bir dosya yolundan yüklenmesi gerektiği anlamına gelir. Bu olmadan dize argümanının kendisi aktarılır.
jimp

93

Kullanıcı kimliğini yol değişkeni olarak yakalamak (önerilir):

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

Formun bir parçası olarak kullanıcı kimliğini yakalamak:

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

veya:

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

16
-F ayarlanmasına gerek yok"Content-Type: multipart/form-data"
William Hu

10
Belirttiğiniz noktalı virgül ayırıcıyla -F'yi düzgün çalıştıramadım. Bunun yerine, iki yedek -F argümanı sağlamak zorunda kaldım. Gibi: -F "data=@test.mp3" -F "kullanıcı kimliği = 1234"
robbpriestley

22

İşte benim çözümüm, çok sayıda gönderi okudum ve gerçekten yardımcı oldular. Sonunda cURL ve PHP ile gerçekten yararlı olduğunu düşünüyorum küçük dosyalar için bazı kod yazdı.

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

}

Bu ile "api.endpoint.post" almak gerekir aşağıdaki yayınlanan vars. Bu komut dosyasıyla kolayca test edebilirsiniz ve bu hata ayıklamalarını postFile()son satırdaki işlevde almanız gerekir .

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>";
}

İyi çalışmalı, daha iyi çözümler olabilirler, ancak bu işe yarar ve Sınır ve çok bölümlü / veri kaynaklı mime'in PHP ve cURL kütüphanesinde nasıl çalıştığını anlamak için gerçekten yararlıdır.


kodlanmamış bir dosya göndermeniz gerekiyorsa bu satırları değiştirin $ BODY. = 'Content-Transfer-Encoding: multipart / form-data'. $ eol. EOL, $; // son İçeriği ve 2 $ eol, $ BODY. = file_get_contents ($ file_url) koyduk. EOL, $; // verileri bitirmek için Base64 Dosya İçeriğini ve $
eol'ü yazıyoruz

8

csv gibi bir ikili dosya yüklüyorsanız, dosyayı yüklemek için aşağıdaki biçimi kullanın

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
İkili bir csv dosyası örneği görmek istiyorum.
polis

4
@polis seçenek --data-binarytalimatını curliçin değil herhangi bir verinin önceden işleme yapmak, aksine --databayrak. yorumunuzu doğrudan ele almak için metnin de ikili olduğunu unutmayın, ancak ASCII karakterleri olarak yorumlayabiliriz. Gerçekten farklı bir örnek istiyorsanız, alanları emoji içeren bir CSV düşünün.
Baytları

3

Beni buraya yönlendiren sorun temel bir kullanıcı hatası olduğu ortaya çıktı - @Dosya yolundaki işareti dahil etmedim ve bu yüzden kıvırmak dosyanın yolunu / adını içerik yerine gönderiyordu. Bu Content-Lengthnedenle değer, test dosyamın efsanesi verildiğini görmeyi beklediğim 479 yerine 8 idi.

Content-LengthBukle dosyasını okur ve mesajlar zaman başlık otomatik olarak hesaplanacaktır.

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

... <İçerik Uzunluğu: 479 ...

Gelecekte diğer yeni başlayanlara yardımcı olmak için buraya gönderiyoruz.


2

Alternatif olarak curl, insanlar için HTTPie , it'a CLI, cURL benzeri bir araç kullanabilirsiniz.

  1. Yükleme talimatları: https://github.com/jakubroztocil/httpie#installation

  2. O zaman koş:

    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

Birçok denemeden sonra bu komut benim için çalıştı:

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

1

Yüklenen dosyaların rastgele dosya adlarından şu şekilde kaçınmak için bash:

#!/bin/bash
set -eu

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

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

0

Bu komutla çalıştım curl -F 'filename=@/home/yourhomedirextory/file.txt' http://yourserver/upload

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.