mariomenjr mariomenjr - 3 months ago 8
PHP Question

PHP unable to upload emails attachments to ftp server

I have been trying to upload to an FTP server the attachments I am getting from an IMAP email, here is my code:

// To retrieve attachments


function attached_file( $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 );
}

/* attached_file return the attachment already decoded. */
/* For this example the encode type was base64, so it used imap_base64 to decode */

function streamed_attach( $filename, $uid, $section, $encoding ) {
/* Returns file as stream using attached_file() returns*/
// error(
// "Filename: $filename\n".
// "UID: $uid\n".
// "Section: $section\n".
// "Encode: $encoding\n"
// );
/*getting decoded string (file)*/
$attach = $this->attached_file( $uid, $section, $encoding );
$attachment = $attach['file'];

$stream = fopen( $filename, 'w+' );
if ( $stream === false ) return false;
//echo htmlspecialchars( $attach['file'] );
$ok = fputs( $stream, $attach['file'] );
echo "Bytes: " . $ok . "<br />";
if ( $ok === false ) return false;
return $stream;
}
?>


streamed_attach receives the return of attached_file and write into the 'handler' $stream.

Then it send that stream ATTENTION: I haven't close the stream, because when I was closing it... ftp_fput was failing. So I left it opened.

However if you see this line

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


It is writing bytes:

BYTES written

// this is to upload to FTP

function login( $user, $pass ) {
if ( $this->conn === false ) {
return false; //Later I'll add more details of why not.
} else {
$this->user = $user; $this->pass = $pass;
$login = @ftp_login($this->conn, $this->user, $this->pass);
$pasv = ftp_pasv( $this->conn, true );
//error( ( $ok != false ) ? "passivo":"no passivo" );
if ( $login && $pasv ) return true; else return false;
}
}

<?php

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

?>


Now, upload_streamed_file receives $stream and using ftp_fput ( because is a pointer ) creates a file on the server... the bad thing is the file is 0 KB sized.

files on server

// this is where I call them

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

$filename = "th.jpg"; //This is the same name as in the email
$uid = 18; $section = 2; $encode = 3;
$path = "POS_ARCHIVE/4700327771/$filename";

echo $filename . "<br />";

if ( $ftp->login( FTP_UID, FTP_PWD ) ) {
$streamed = "";
$streamed = $mailbox->streamed_attach(
$filename, $uid, $section, $encode
); //$mailbox I have the instance before.
$ok = $ftp->upload_streamed_file( $streamed, $path );
if ( $ok ) { echo "Good!"; } else { echo "Bad!"; }
} else echo "Buuuuu";


Can you help me, I've been 2 hours with this...

Answer

When streamed_attach() returns, the file pointer for the stream is pointing to the end of the file. So when you try to upload it with ftp_fput(), it immediately reads EOF and uploads an empty file. You need to go back to the beginning of the file so you can read what you've written to the file.

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

An alternative would be to close the stream in streamed_attach(), and then use ftp_put with the filename instead of ftp_fput with the stream.

Comments