Mi rendo conto di poterlo fare molto facilmente con CURL, ma mi chiedevo se fosse possibile utilizzare file_get_contents()
con il contesto del flusso http per caricare un file su un server Web remoto e, in tal caso, come ?Carica un file utilizzando file_get_contents
risposta
Prima di tutto, la prima regola di multipart
Content-Type è di definire un contorno che verrà utilizzato come delimitatore tra ogni parte (perché, come dice il nome, si può avere più parti). Il limite può essere qualsiasi stringa che non è contenuta nel corpo del contenuto. Io di solito uso un timestamp:
define('MULTIPART_BOUNDARY', '--------------------------'.microtime(true));
Una volta che il confine è definito, è necessario inviare con l'intestazione Content-Type
per dire al server web che cosa delimitatore aspettarsi:
$header = 'Content-Type: multipart/form-data; boundary='.MULTIPART_BOUNDARY;
Una volta fatto ciò, si deve creare un corpo di contenuto adeguato che corrisponda alle specifiche HTTP e all'intestazione che hai inviato. Come sapete, quando si invia un file da un modulo, di solito si ha un nome di campo modulo. Ci definiamo:
// equivalent to <input type="file" name="uploaded_file"/>
define('FORM_FIELD', 'uploaded_file');
Poi costruire il corpo contenuto:
$filename = "/path/to/uploaded/file.zip";
$file_contents = file_get_contents($filename);
$content = "--".MULTIPART_BOUNDARY."\r\n".
"Content-Disposition: form-data; name=\"".FORM_FIELD."\"; filename=\"".basename($filename)."\"\r\n".
"Content-Type: application/zip\r\n\r\n".
$file_contents."\r\n";
// add some POST fields to the request too: $_POST['foo'] = 'bar'
$content .= "--".MULTIPART_BOUNDARY."\r\n".
"Content-Disposition: form-data; name=\"foo\"\r\n\r\n".
"bar\r\n";
// signal end of request (note the trailing "--")
$content .= "--".MULTIPART_BOUNDARY."--\r\n";
Come potete vedere, stiamo inviando il Content-Disposition
intestazione con il form-data
disposizione, insieme con il parametro name
(il nome del campo modulo) e il parametro filename
(il nome file originale). È inoltre importante inviare l'intestazione Content-Type
con il tipo MIME corretto, se si desidera compilare correttamente il numero $_FILES[]['type']
.
Se avevi più file da caricare, basta ripetere il processo con il contenuto $ bit, con ovviamente un diverso FORM_FIELD
per ogni file.
Ora, costruire il contesto:
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => $header,
'content' => $content,
)
));
ed eseguire:
file_get_contents('http://url/to/upload/handler', false, $context);
NOTA: Non v'è alcuna necessità di codificare il file binario prima di inviarlo. HTTP può gestire il binario bene.
Wow, bella risposta. Ci proveremo stasera. – Shabbyrobe
Questo ha funzionato magnificamente. C'è qualche possibilità che tu possa aggiungere alla tua risposta come aggiungere campi addizionali con il caricamento? Inoltre, è possibile fare multipli in questo modo semplicemente virando su un altro confine? – Shabbyrobe
Sicuro. Per i campi POST, vedere la mia risposta aggiornata. Per quanto riguarda la tua seconda domanda, non sono sicuro di cosa intendi. – netcoder
È possibile inviare una richiesta POST
con Content-Type: multipart/form-data
e codificare manualmente il file come multipart/form-data
.
file_get_contents(URL, false, stream_context_create(array(
'http' => array(
'method' => 'POST',
'headers' => 'Content-Type: multipart/form-data'
'content' => MULTIPART_ENCODED_FILE,
),
)));
come faccio a codificare il file? – Shabbyrobe
@Shabbyrobe: Sì, questa è esattamente la domanda ... Non ho idea di come funzioni la codifica in più parti, quindi non posso aiutarti. – NikiC
Prova 'base64_encode()', http://php.net/manual/en/function.base64-encode.php. –
Non intendi file_put_contents()? – mellowsoon
No. Prova a fare file_put_contents con un URL e otterrai "HTTP wrapper non supporta connessioni scrivibili" – Shabbyrobe
Ma con * file_get_contents() * puoi scaricare file, non caricare !? – KingCrunch