Amazon S3 - Your proposed upload is smaller than the minimum allowed size

This error occurs when one of the parts is less than 5MB in size and isn't the last part (the last part can be any size). fread() can return a string shorter than the specified size, so you need to keep calling fread() until you have at least 5MB of data (or you have reached the end of the file) before uploading that part.

So your 3rd step becomes:

// 3. Upload the file in parts.
$file = fopen($filename, 'r');
$parts = array();
$partNumber = 1;
while (!feof($file)) {

    // Get at least 5MB or reach end-of-file
    $data = '';
    $minSize = 5 * 1024 * 1024;
    while (!feof($file) && strlen($data) < $minSize) {
        $data .= fread($file, $minSize - strlen($data));
    }

    $result = $client->uploadPart(array(
        'Bucket'     => $bucket,
        'Key'        => $keyname,
        'UploadId'   => $uploadId,
        'PartNumber' => $partNumber,
        'Body'       => $data, // <= send our buffered part
    ));
    $parts[] = array(
        'PartNumber' => $partNumber++,
        'ETag'       => $result['ETag'],
    );
}

The minimal multipart upload size is 5Mb (1), even if your total size is 100MB, each individual multipart upload (other than the last one) can't be smaller than 5MB. You probably want to use a "normal" upload, not a multipart upload.

(1) http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html