Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Upload не из html-формы


Автор: GavriKos 12.5.2011, 11:08
Доброго времени суток. Есть задача - нужно реализовать аплоад файлов на сервер не через html-форму, а из обычного приложения. В приложении отправляю обычный POST-запрос (без енкодинга как для заливки файлов). В пхп-скрипте подразумевается присланные данные в POSTе сохранить в бинарный файл. Написал на пхп вот такой код:

Код

<?php
$file = fopen("log","wb");
$size = $_POST["len"];
for ($i=0;$i<$size;$i++)
    //fputs($file,$_POST['file'][$i],1);
    //fprintf($file,"%c",($_POST['file'][$i]));
    
    fwrite($file,$_POST['file'][$i],1);
fclose($file);
?> 


Вроде все правильно, но такой код сохраняет файл в текстовом виде, а не в бинарном. fputs тоже дает текстовый файл. ПРичем размер текстового меньше (намного) размера передаваемого бинарника - срабатывает какая то перекодировка. Единственный вариант, который выдал бинарный файл
 
Код

fprintf($file,"%c",($_POST['file'][$i]));

Причем именно "%c" (%s дает текстовый файл). Но при этом данные все равно были сохранены неправильно (80% файла - пустые символы, причем даже реально читаемые символы в бинарнике не записываются таким методом).

Прочитал про отмену перекодировки путем прописывания пары строчек в htaccess - не помогло.

Кто что подскажет по проблеме?

Автор: MoLeX 12.5.2011, 12:26
Цитата(GavriKos @  12.5.2011,  11:08 Найти цитируемый пост)
Есть задача - нужно реализовать аплоад файлов на сервер не через html-форму, а из обычного приложения.

Цитата(GavriKos @  12.5.2011,  11:08 Найти цитируемый пост)
В приложении отправляю обычный POST-запрос


Код

var_dump($_FILES);


Автор: GavriKos 12.5.2011, 17:01
Может 
Код

var_dump($_POST['file']);

?

Выяснил, что пхп кодирует по-своему некоторые символы, вне зависимости от того, как ему передаются данные. Соответственно надо на стороне отправляющей данные перекодировать так, чтобы пхп ничего с ними не сделал, но это другой вопрос.

А вот вопрос о корректности выкидывания в файл остался - fwrite записывает меньше данных, причем существенно. Даже если принудительно, в цикле вычитывать по одному символу. Символов окончания строки нету в теле.

Автор: bars80080 12.5.2011, 18:57
Цитата(GavriKos @  12.5.2011,  17:01 Найти цитируемый пост)
Может 
Выделить всёкод PHP
1:
    
var_dump($_POST['file']);

?

нет. посмотрите, что вам приходит в массиве $_FILES

пхп до фени, какой клиент передаёт ему данные, он принимает их одинаково. поэтому вы можете брать любой пхп-скрипт серверной обработки загружаемых файлов, и он подойдёт, что для хтмл-формы с вэб-странички, что для вашего приложения.

данные о приходящих файлах записываются в массив $_FILES, и никак не $_POST или $_GET

Автор: GavriKos 12.5.2011, 19:52
1) С дампом переменной ничего не получится - прога не обрабатывает то, что вывелось скриптом на страницу. Так что судить о результатах можно только по файлам
2) Все таки по поводу $_FILES - если я отправляю самый обычный пост-запрос, с телом file=содержимое_файла, то пхп вроде ничего в $_FILES не запишет. Запрос самый обычный, без указания о том, что идет файл.

Автор: MoLeX 13.5.2011, 05:24
GavriKos, не знаю как вы отправляете данные и с помощью какого языка, поэтому привожу пример для C++ Builder
Код

#include <IdMultipartFormData.hpp>

TStringStream *Result = new TStringStream("");
TIdMultiPartFormDataStream *Data= new TIdMultiPartFormDataStream();
Data->AddFile("fileupload", "D:\\file.txt", "multipart/form-data");

IdHTTP1->Request->ContentType = Data->RequestContentType;
IdHTTP1->Request->ContentLength = Data->Size;
IdHTTP1->Post("http://127.0.0.1/test.php", Data, Result);

Memo1->Text = Result->DataString;


и на сервере test.php
Код

var_dump($_FILES);

Автор: ksnk 13.5.2011, 05:53
Цитата(GavriKos @  12.5.2011,  19:52 Найти цитируемый пост)
 Все таки по поводу $_FILES - если я отправляю самый обычный пост-запрос, с телом file=содержимое_файла

Получится неправильно. Для метода POST существует http://phpclub.ru/detail/article/http_request#part_3 multipart/form-data и application/x-www-form-urlencoded. Второй используется по умолчанию. Как можно заметить, для первого следует соблюдать "границы", со вторым - кодировать служебные символы в urlencode стиле.

Автор: GavriKos 13.5.2011, 08:05
ksnk, отправляю именно в application/x-www-form-urlencoded. Вывод - лучше разобраться как отправлять в multipart/form-data )) Тогда и дамп будет актуальнее.


MoLeX, отправляю через связку c++ + wxCurl. Типа кодирования в параметрах нету. Или не нашел (

Автор: MoLeX 13.5.2011, 08:23
посмотри компонент IdHTTP, Indy лучше последние

Автор: GavriKos 13.5.2011, 10:14
MoLeX, это, я так понял, библиотеки для работы с вебом... Уже пол проекта на wxCurl писано. Но мысль с кодированием правильная?

Автор: ksnk 13.5.2011, 12:52
Код

file_get_contents('php://input');

сохранить в файл и помедитировать.
Вроде, то, что посылается, то и должно прилететь для application/x-www-form-urlencoded

Автор: GavriKos 13.5.2011, 15:25
Код

<?php
$file = fopen("log",'wb');
fwrite(file_get_contents("php:\\input"));
fclose($file);
?> 


Пустой файл н выходе ( Данны еточно посылаются.

Автор: bars80080 13.5.2011, 17:36
Цитата(GavriKos @  13.5.2011,  15:25 Найти цитируемый пост)
$file = fopen("log",'wb');

первый раз вижу модификатор wb

Добавлено через 1 минуту и 10 секунд
Цитата(GavriKos @  13.5.2011,  15:25 Найти цитируемый пост)
fwrite(file_get_contents("php:\\input"));

а это вообще как получилось?

http://ru2.php.net/manual/en/function.fwrite.php

Автор: Pfailed 14.5.2011, 16:04
libcurl умеет multipart, подозреваю что его wx оболочка тоже. http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTHTTPPOST

Автор: GavriKos 14.5.2011, 21:39
bars80080, wb - нормальный модификатор. w - создать для записи, b - бинарный режим.

Автор: ksnk 14.5.2011, 21:56
GavriKos, а то, что fwrite нужно передать этот самый $file параметром - ничего?

Автор: GavriKos 14.5.2011, 22:53
Блин, точно  smile  . Завтра проверю.

Автор: GavriKos 15.5.2011, 15:49
Проверил. Код вида:
Код

fwrite($file,file_get_contents("php://input"));

порезал все после первого символа окончания строки. Попробовал так - в проге заменил все окончания строки на некоторую последовательность символов - заработало почти правильно (в конце чуть чуть недотянуло байтов, но это уже решаемо). Итого код получился такого вот вида:

Код

<?php
$file = fopen("log",'wb');

$arr = file_get_contents("php://input");
$size = $_POST["len"];

for ($i=16;$i<$size;$i++)

    if (($arr[$i]=='%')&&($arr[$i+1]=='4')&&($arr[$i+3]=='%')&&($arr[$i+2]=='4'))
    {
        fprintf($file,"%c",0x00);
        $i+=3;
    }
    else
    fwrite($file,$arr[$i],1);
fclose($file);
?> 


Автор: ksnk 15.5.2011, 17:19
а если сделать $arr = file("php://input"); Оно, случайно, не нарежется на строки как надо?

Автор: Pfailed 15.5.2011, 17:59
Что за костылестроением вы тут занимаетесь? Идите читайте документацию по libcurl и принимайте файл через $_FILES.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)