Start a multipart upload operation.

        :type key_name: string
        :param key_name: The name of the key that will ultimately result from
                         this multipart upload operation.  This will be exactly
                         as the key appears in the bucket after the upload
                         process has been completed.

        :type headers: dict
        :param headers: Additional HTTP headers to send and store with the
                        resulting key in S3.

        :type reduced_redundancy: boolean
        :param reduced_redundancy: In multipart uploads, the storage class is
                                   specified when initiating the upload,
                                   not when uploading individual parts.  So
                                   if you want the resulting key to use the
                                   reduced redundancy storage class set this
                                   flag when you initiate the upload.

        :type metadata: dict
        :param metadata: Any metadata that you would like to set on the key
                         that results from the multipart upload.
                         
        :type encrypt_key: bool
        :param encrypt_key: If True, the new copy of the object will
                            be encrypted on the server-side by S3 and
                            will be stored in an encrypted form while
                            at rest in S3.

def initiate_multipart_upload(self, key_name, headers=None,
                                  reduced_redundancy=False,
                                  metadata=None, encrypt_key=False):
        """
        Start a multipart upload operation.

        :type key_name: string
        :param key_name: The name of the key that will ultimately result from
                         this multipart upload operation.  This will be exactly
                         as the key appears in the bucket after the upload
                         process has been completed.

        :type headers: dict
        :param headers: Additional HTTP headers to send and store with the
                        resulting key in S3.

        :type reduced_redundancy: boolean
        :param reduced_redundancy: In multipart uploads, the storage class is
                                   specified when initiating the upload,
                                   not when uploading individual parts.  So
                                   if you want the resulting key to use the
                                   reduced redundancy storage class set this
                                   flag when you initiate the upload.

        :type metadata: dict
        :param metadata: Any metadata that you would like to set on the key
                         that results from the multipart upload.
                         
        :type encrypt_key: bool
        :param encrypt_key: If True, the new copy of the object will
                            be encrypted on the server-side by S3 and
                            will be stored in an encrypted form while
                            at rest in S3.
        """
        query_args = 'uploads'
        provider = self.connection.provider
        if headers is None:
            headers = {}
        if reduced_redundancy:
            storage_class_header = provider.storage_class_header
            if storage_class_header:
                headers[storage_class_header] = 'REDUCED_REDUNDANCY'
            # TODO: what if the provider doesn't support reduced redundancy?
            # (see boto.s3.key.Key.set_contents_from_file)
        if encrypt_key:
            headers[provider.server_side_encryption_header] = 'AES256'
        if metadata is None:
            metadata = {}

        headers = boto.utils.merge_meta(headers, metadata,
                self.connection.provider)
        response = self.connection.make_request('POST', self.name, key_name,
                                                query_args=query_args,
                                                headers=headers)
        body = response.read()
        boto.log.debug(body)
        if response.status == 200:
            resp = MultiPartUpload(self)
            h = handler.XmlHandler(resp, self)
            xml.sax.parseString(body, h)
            return resp
        else:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)