Menggunakan ikal untuk mengunggah data POST dengan file

415

Saya ingin menggunakan cURL untuk tidak hanya mengirim parameter data dalam HTTP POST tetapi juga mengunggah file dengan nama formulir tertentu. Bagaimana saya harus melakukan itu?

Parameter Posting HTTP:

userid = 12345 filecomment = Ini adalah file gambar

Unggah File HTTP: Lokasi file = /home/user1/Desktop/test.jpg Nama formulir untuk file = gambar (sesuai dengan $ _FILES ['gambar'] di sisi PHP)

Saya menganggap bagian dari perintah CURL sebagai berikut:

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

Masalah yang saya dapatkan adalah sebagai berikut:

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

Masalahnya adalah saya menggunakan $ _FILES ['gambar'] untuk mengambil file dalam skrip PHP.

Bagaimana cara menyesuaikan perintah CURL saya?

thotheolh
sumber

Jawaban:

657

Anda perlu menggunakan -Fopsi:
-F/--form <name=content> Specify HTTP multipart POST data (H)

Coba ini:

curl \
  -F "userid=1" \
  -F "filecomment=This is an image file" \
  -F "image=@/home/user1/Desktop/test.jpg" \
  localhost/uploader.php
sederhana sekali
sumber
1
Saya bingung dengan bagian tentang url-encoding file. Saya telah mengunggah file JPG dan PNG seperti ini tanpa memodifikasinya, tanpa masalah.
Deanna Gelbart
1
@ DavidGelbart Anda benar. Jawaban awal saya merujuk -dopsi secara tidak sengaja, yang membutuhkan input URL-disandikan. Saya seharusnya menghapus itu ketika saya memperbarui jawaban untuk -Fopsi. Terima kasih sudah menangkapnya.
jimp
3
@ user956424 Pada contoh, atur "image" ke nama bidang Anda. Dan beberapa bahasa, seperti PHP, akan membangun array jika Anda menentukan sesuatu seperti "image []" untuk input yang perlu dikelompokkan bersama.
gendut
1
Apa @di image=@/..?
Timo
2
@Timo Ini berarti konten untuk bidang formulir bernama harus diambil dari jalur file. Tanpanya argumen string itu sendiri dilewatkan.
jimp
94

Menangkap id pengguna sebagai variabel jalur (disarankan):

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "[email protected]" http://mysuperserver/media/1234/upload/

Menangkap id pengguna sebagai bagian dari formulir:

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "[email protected];userid=1234" http://mysuperserver/media/upload/

atau:

curl -i -X POST -H "Content-Type: multipart/form-data" 
-F "[email protected]" -F "userid=1234" http://mysuperserver/media/upload/
r1ckr
sumber
16
gunakan -F tidak perlu diatur"Content-Type: multipart/form-data"
William Hu
10
Saya tidak bisa -F bekerja dengan benar dengan pemisah titik koma yang Anda sebutkan. Sebaliknya, saya harus memberikan dua argumen -F yang berlebihan. Seperti: -F "[email protected]" -F "userid = 1234"
robbpriestley
22

Inilah solusi saya, saya telah membaca banyak posting dan mereka sangat membantu. Akhirnya saya menulis beberapa kode untuk file kecil, dengan cURL dan PHP yang menurut saya sangat berguna.

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

}

Dengan ini kita harus berada di "api.endpoint.post" vars berikut diposting. Anda dapat dengan mudah menguji dengan skrip ini, dan Anda harus menerima debug ini pada fungsi postFile()di baris terakhir.

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

Seharusnya bekerja dengan baik, mereka mungkin solusi yang lebih baik tetapi ini berfungsi dan sangat membantu untuk memahami bagaimana Bimeary dan multipart / dari-data mime bekerja di PHP dan perpustakaan CURL.

Libertese
sumber
jika Anda perlu mengirim file yang tidak disandikan, ubah baris ini $ BODY. = 'Content-Transfer-Encoding: multipart / form-data'. $ eol. $ eol; // kita letakkan Konten terakhir dan $ 2 eol, $ BODY. = file_get_contents ($ file_url). $ eol; // kami menulis Konten File Base64 dan $ eol untuk menyelesaikan data,
andreah
8

jika Anda mengunggah file biner seperti csv, gunakan format di bawah ini untuk mengunggah file

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'
KARTHIKEYAN.A
sumber
4
Saya ingin melihat contoh file csv biner.
polis
4
@polis opsi --data-binarymenginstruksikan curluntuk tidak melakukan pra-pemrosesan data, sebagai lawan dari --dataflag. untuk menanggapi komentar Anda secara langsung, perhatikan bahwa teks juga biner, tetapi kami dapat menafsirkannya sebagai karakter ASCII. Jika Anda benar-benar menginginkan contoh berbeda, pikirkan tentang CSV yang isinya berisi emoji. Bytes mereka tidak langsung dipetakan ke teks
Ciprian Tomoiagă
3

Masalah yang membawa saya ke sini ternyata merupakan kesalahan pengguna dasar - saya tidak memasukkan @tanda di jalur file dan jadi ikal memposting path / nama file daripada konten. The Content-Lengthsehingga nilai adalah 8 daripada 479 yang saya harapkan untuk lihat mengingat legnth file pengujian saya.

The Content-Lengthheader akan otomatis dihitung ketika ikal membaca dan posting file.

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

... <Panjang Konten: 479 ...

Posting ini di sini untuk membantu pemula lain di masa depan.

pengguna linux shonky
sumber
2

Sebagai alternatif curl, Anda dapat menggunakan HTTPie , itu CLI, alat seperti Curl untuk manusia.

  1. Petunjuk instalasi: https://github.com/jakubroztocil/httpie#installation

  2. Lalu lari:

    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
    
    ...
Gianfranco P.
sumber
2

Setelah banyak mencoba, perintah ini berhasil untuk saya:

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

Berikut adalah cara keluar dari nama file yang diunggah dengan file sewenang-wenang dengan bash:

#!/bin/bash
set -eu

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

curl --silent --form "uploaded=@\"$f\"" "$2"
Vladimir Panteleev
sumber
0

Saya berhasil dengan perintah ini curl -F 'filename=@/home/yourhomedirextory/file.txt' http://yourserver/upload

Hebra Shraavan
sumber