8 * This source file is subject to the new BSD license that is bundled
9 * with this package in the file LICENSE.txt.
10 * It is also available through the world-wide-web at this URL:
11 * http://framework.zend.com/license/new-bsd
12 * If you did not receive a copy of the license and are unable to
13 * obtain it through the world-wide-web, please send an email
14 * to license@zend.com so we can send you a copy immediately.
19 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
20 * @license http://framework.zend.com/license/new-bsd New BSD License
25 * @see Zend_Gdata_MimeFile
27 require_once 'Zend/Gdata/MimeFile.php';
30 * @see Zend_Gdata_MimeBodyString
32 require_once 'Zend/Gdata/MimeBodyString.php';
36 * A streaming Media MIME class that allows for buffered read operations.
41 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
42 * @license http://framework.zend.com/license/new-bsd New BSD License
44 class Zend_Gdata_MediaMimeStream
48 * A valid MIME boundary.
52 protected $_boundaryString = null;
55 * A handle to the file that is part of the message.
59 protected $_fileHandle = null;
62 * The current part being read from.
65 protected $_currentPart = 0;
68 * The size of the MIME message.
71 protected $_totalSize = 0;
74 * An array of all the parts to be sent. Array members are either a
75 * MimeFile or a MimeBodyString object.
78 protected $_parts = null;
81 * Create a new MimeMediaStream object.
83 * @param string $xmlString The string corresponding to the XML section
84 * of the message, typically an atom entry or feed.
85 * @param string $filePath The path to the file that constitutes the binary
86 * part of the message.
87 * @param string $fileContentType The valid internet media type of the file.
88 * @throws Zend_Gdata_App_IOException If the file cannot be read or does
89 * not exist. Also if mbstring.func_overload has been set > 1.
91 public function __construct($xmlString = null, $filePath = null,
92 $fileContentType = null)
94 if (!file_exists($filePath) || !is_readable($filePath)) {
95 require_once 'Zend/Gdata/App/IOException.php';
96 throw new Zend_Gdata_App_IOException('File to be uploaded at ' .
97 $filePath . ' does not exist or is not readable.');
100 $this->_fileHandle = fopen($filePath, 'rb', TRUE);
101 $this->_boundaryString = '=_' . md5(microtime(1) . rand(1,20));
102 $entry = $this->wrapEntry($xmlString, $fileContentType);
103 $closingBoundary = new Zend_Gdata_MimeBodyString("\r\n--{$this->_boundaryString}--\r\n");
104 $file = new Zend_Gdata_MimeFile($this->_fileHandle);
105 $this->_parts = array($entry, $file, $closingBoundary);
107 $fileSize = filesize($filePath);
108 $this->_totalSize = $entry->getSize() + $fileSize
109 + $closingBoundary->getSize();
114 * Sandwiches the entry body into a MIME message
118 private function wrapEntry($entry, $fileMimeType)
120 $wrappedEntry = "--{$this->_boundaryString}\r\n";
121 $wrappedEntry .= "Content-Type: application/atom+xml\r\n\r\n";
122 $wrappedEntry .= $entry;
123 $wrappedEntry .= "\r\n--{$this->_boundaryString}\r\n";
124 $wrappedEntry .= "Content-Type: $fileMimeType\r\n\r\n";
125 return new Zend_Gdata_MimeBodyString($wrappedEntry);
129 * Read a specific chunk of the the MIME multipart message.
131 * @param integer $bufferSize The size of the chunk that is to be read,
132 * must be lower than MAX_BUFFER_SIZE.
133 * @return string A corresponding piece of the message. This could be
134 * binary or regular text.
136 public function read($bytesRequested)
138 if($this->_currentPart >= count($this->_parts)) {
142 $activePart = $this->_parts[$this->_currentPart];
143 $buffer = $activePart->read($bytesRequested);
145 while(strlen($buffer) < $bytesRequested) {
146 $this->_currentPart += 1;
147 $nextBuffer = $this->read($bytesRequested - strlen($buffer));
148 if($nextBuffer === FALSE) {
151 $buffer .= $nextBuffer;
158 * Return the total size of the mime message.
160 * @return integer Total size of the message to be sent.
162 public function getTotalSize()
164 return $this->_totalSize;
168 * Close the internal file that we are streaming to the socket.
172 public function closeFileHandle()
174 if ($this->_fileHandle !== null) {
175 fclose($this->_fileHandle);
180 * Return a Content-type header that includes the current boundary string.
182 * @return string A valid HTTP Content-Type header.
184 public function getContentType()
186 return 'multipart/related;boundary="' .
187 $this->_boundaryString . '"' . "\r\n";