Загрузка, изменение и повторная загрузка изображения без сохранения [дубликатов]

CRTP - это метод реализации полиморфизма времени компиляции. Вот очень простой пример. В приведенном ниже примере ProcessFoo() работает с интерфейсом класса Base, а Base::Foo вызывает метод foo() производного объекта, который вы намерены делать с виртуальными методами.

http://coliru.stacked-crooked.com/a/2d27f1e09d567d0e

template 
struct Base {
  void foo() {
    (static_cast(this))->foo();
  }
};

struct Derived : public Base {
  void foo() {
    cout << "derived foo" << endl;
  }
};

struct AnotherDerived : public Base {
  void foo() {
    cout << "AnotherDerived foo" << endl;
  }
};

template
void ProcessFoo(Base* b) {
  b->foo();
}


int main()
{
    Derived d1;
    AnotherDerived d2;
    ProcessFoo(&d1);
    ProcessFoo(&d2);
    return 0;
}

Выход:

derived foo
AnotherDerived foo

35
задан gawpertron 22 June 2010 в 22:19
поделиться

2 ответа

Должно быть возможно: вот форма, размещенная через браузер (нерелевантные поля опущены):

POST http://host.example.com/somewhere HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------7da16b2e4026c
Content-Length: 105732

-----------------------------7da16b2e4026c
Content-Disposition: form-data; name="NewFile"; filename="test.jpg"
Content-Type: image/jpeg

(...raw JPEG data here...)
-----------------------------7da16b2e4026c
Content-Disposition: form-data; name="otherformfield"

content of otherformfield is this text
-----------------------------7da16b2e4026c--

Итак, если мы сами построим тело POST и установим дополнительный заголовок или два, мы должны уметь имитировать это:

// form field separator
$delimiter = '-------------' . uniqid();
// file upload fields: name => array(type=>'mime/type',content=>'raw data')
$fileFields = array(
    'file1' => array(
        'type' => 'text/plain',
        'content' => '...your raw file content goes here...'
    ), /* ... */
);
// all other fields (not file upload): name => value
$postFields = array(
    'otherformfield'   => 'content of otherformfield is this text',
    /* ... */
);

$data = '';

// populate normal fields first (simpler)
foreach ($postFields as $name => $content) {
   $data .= "--" . $delimiter . "\r\n";
    $data .= 'Content-Disposition: form-data; name="' . $name . '"';
    // note: double endline
    $data .= "\r\n\r\n";
}
// populate file fields
foreach ($fileFields as $name => $file) {
    $data .= "--" . $delimiter . "\r\n";
    // "filename" attribute is not essential; server-side scripts may use it
    $data .= 'Content-Disposition: form-data; name="' . $name . '";' .
             ' filename="' . $name . '"' . "\r\n";
    // this is, again, informative only; good practice to include though
    $data .= 'Content-Type: ' . $file['type'] . "\r\n";
    // this endline must be here to indicate end of headers
    $data .= "\r\n";
    // the file itself (note: there's no encoding of any kind)
    $data .= $file['content'] . "\r\n";
}
// last delimiter
$data .= "--" . $delimiter . "--\r\n";

$handle = curl_init($url);
curl_setopt($handle, CURLOPT_POST, true);
curl_setopt($handle, CURLOPT_HTTPHEADER , array(
    'Content-Type: multipart/form-data; boundary=' . $delimiter,
    'Content-Length: ' . strlen($data)));  
curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
curl_exec($handle);

Таким образом, мы делаем все тяжелое поднятие себя и доверяем cURL, чтобы не калечить его.

25
ответ дан Piskvor 20 August 2018 в 21:12
поделиться
  • 1
    Первоначально неверно изложил вопрос и получил справедливое решение за него. Переписано во что-то, что может сработать. – Piskvor 21 June 2010 в 17:12
  • 2
    Я построил запрос, как предложил Писквор, и да, вы можете сами построить тело, и оно будет работать. Хотя вы должны быть на 100% точнее с EOL. В конце «Content-Length», и "Content-Disposition" требуется двойной возврат. Для файла после & quot; Content-Type: text / plain & quot; требуется двойной возврат. Разделитель также немного отличается для значений тела, чем это укорачивается в «Границе». Каждая граничная линия имеет два дополнительных дефиса, предшествующих началу. Последний разделитель имеет два дополнительных подменю в начале и в конце. – gawpertron 22 June 2010 в 13:00
  • 3
    @ Крис Генри: Действительно. Я предлагаю вам прочитать вопрос; quote: «Я знаю, что вы можете опубликовать файл, который уже находится в файловой системе, путем префикса пути к файлу с помощью & quot; @ & quot ;. Однако я хотел бы обойти создание временного файла ... & quot; Итак, ваше решение «как это сделать без @ / some / file / name? & Quot; "использовать @ / some / file / name & quot ;? Ум, он боится ... – Piskvor 18 February 2011 в 09:48
  • 4
    При заполнении $postFields в конце первого foreach вам не хватает $data .= $content . "\r\n";, иначе содержимое поля не будет отправлено. – Cesar 18 July 2013 в 18:27
  • 5
    Спасибо, @Piskvor! Примечание по типу "name =" в строке Content-Disposition. Он должен быть установлен на имя элемента, который получил бы & quot; @ & quot; файл в массиве, присвоенный CURLOPT_POSTFIELDS. Если вы установите файл в curl_setopts CurlFile с параметром $ params- & gt; file = & quot; @ myfilename.pdf & quot ;, то вам понадобится имя = & quot; файл & quot ;. Я подозреваю, что это то же самое, что и имя тэга & quot; в HTML. Устанавливать его так же, как имя файла, возможно, не так, как того хочет сервер. – Mark Kasson 18 September 2015 в 14:02

php имеет доступ к временному местоположению «php: // memory», что фактически делает то, что вы пытаетесь сделать довольно легко.

$fh = fopen('php://memory','rw');
fwrite( $fh, $content);
rewind($fh);

$options = array(
    CURLOPT_RETURNTRANSFER  => true
    ,CURLOPT_SSL_VERIFYPEER => false
    ,CURLOPT_SSL_VERIFYHOST => 1
    ,CURLOPT_HTTPHEADER     => array(
        'Content-type: multipart/form-data'
    )
    ,CURLOPT_INFILE         => $fh
    ,CURLOPT_INFILESIZE     => strlen($content)
);
15
ответ дан erik.wiffin 20 August 2018 в 21:12
поделиться
  • 1
    Будет ли это использоваться для остальных почтовых полей, которые отправляются вместе с файлом? – Neil Aitken 21 June 2010 в 17:16
  • 2
    Он определенно создает обработчик файлов, и я дал ему попробовать, но я думаю, что CURLOPT_INFILE и CURLOPT_INFILESIZE используются для PUT-файлов, в массиве $ _FILES файлов не обнаружено. – gawpertron 21 June 2010 в 19:32
  • 3
    Код в вопросе может загружать сразу несколько файлов. Может ли PUT загрузить INFILE несколько файлов? – DanFromGermany 10 July 2013 в 14:31
  • 4
    Удивительное решение, спасибо! – Nate 7 December 2013 в 04:41
Другие вопросы по тегам:

Похожие вопросы: