PHP не удается загрузить вложения электронной почты на ftp-сервер


Я пытался загрузить на FTP-сервер вложения, которые я получаю по электронной почте IMAP, вот мой код:

Для извлечения вложений

<?php
    /* 
        attachedFile() returns the attachment already decoded.
        For this example the encode type was base64, so it used imap_base64 to decode 
    */
    function attachedFile($uid, $section, $encoding) {
        # Returns file as an encoded string
        $file = imap_fetchbody($this->conn, $uid, $section, FT_UID); 

        switch ($encoding) {
            case 0:
            case 1:
                $file = imap_8bit($file); break;
            case 2:
                $file = imap_binary($file); break;
            case 3:
                $file = imap_base64($file); break;
            case 4:
                $file = quoted_printable_decode($file); break;
        }
        $mime = imap_fetchmime($this->conn, $uid, $section, FT_UID);

        # returning decoding file, I use mime in another section
        return array('file' => $file, 'mime' => $mime);
    }

    /* 
        Returns file as stream using attached_file() returns
    */
    function streamedAttach( $filename, $uid, $section, $encoding ) {
        # Returns file as stream using attached_file() returns
        $attach = $this->attachedFile($uid, $section, $encoding);
        $attachment = $attach['file'];

        $stream = fopen($filename, 'w+');
        if ( $stream === false ) return false;

        $ok = fputs($stream, $attach['file']);

        # raw printing
        echo "Bytes: " . $ok . "<br />";

        if ($ok===false) return false;

        return $stream;
    }
?>

Streamedattach получает возврат вложенного файла и записывает его в "обработчик" $stream.

Затем он отправляет этот поток ВНИМАНИЕ: Я не закрыл поток, потому что, когда я закрывал его... ftp_fput не удался. Поэтому я оставил ее открытой.

Однако, если вы видите эту строку

echo "Bytes: " . $ok . "<br />";

Это запись байтов:

Записанные байты

Это для загрузки на FTP

function login($user, $pass) {
    $ok = $this->conn!==false;
    if ($ok) {
        # Credentials
        $this->user = $user; 
        $this->pass = $pass;

        $login = @ftp_login($this->conn, $this->user, $this->pass);
        $pasv = ftp_pasv($this->conn, true);

        $ok = ($login && $pasv);
    }
    return $ok;
}

function uploadStreamedFile($stream, $destination) {
    $ok = $this->conn!==false;
    if ($ok) {
        $ok = ftp_fput($this->conn, $destination, $stream, FTP_BINARY);
        fclose($stream);
    }
    return $ok;
}

Теперь upload_streamed_file получает $stream и с помощью ftp_fput (потому что это указатель) создает файл на сервере... плохо то, что размер файла составляет 0 КБ.

Файлы на сервере

Вот где я их называю

$ftp = new ftp_conn();
$ftp->basePath = "POS_ARCHIVE";

# This is the same name as in the email
$filename = "th.jpg"; 

# Sample data
$uid = 18; 
$section = 2; 
$encode = 3;
$path = "POS_ARCHIVE/4700327771/$filename";

echo $filename . "<br />";

if ($ftp->login(FTP_UID, FTP_PWD)) {

        # $mailbox I have the instance before.
        $streamed = $mailbox->streamedAttach($filename, $uid, $section, $encode);
        $ok = $ftp->uploadStreamedFile($streamed, $path);
        if ( $ok ) echo "There you go!";
        else echo "Nope, nope.";
} else 
    echo "Nope, nope.";

Не могли бы вы мне помочь, я занимаюсь этим уже 2 часа...

Author: mariomenjr, 2016-08-06

1 answers

Когда streamed_attach() возвращается, указатель файла для потока указывает на конец файла. Поэтому, когда вы пытаетесь загрузить его с помощью ftp_fput(), он немедленно считывает EOF и загружает пустой файл. Вам нужно вернуться к началу файла, чтобы вы могли прочитать то, что вы записали в файл.

function upload_streamed_file( $stream, $destination ) {
   if ( $this->conn === false ) {
       return false; //Later I'll add more details of why not.
   } else {
       //error( $destination );
       rewind($stream);
       $ok = ftp_fput( $this->conn, $destination, $stream, FTP_BINARY );
       fclose( $stream );
       return $ok;
   }
}

Альтернативой было бы закрыть поток в streamed_attach(), а затем использовать ftp_put с именем файла вместо ftp_fput с потоком.

 1
Author: Barmar, 2016-08-05 22:51:48