def _send_media_body(self, start): """ Send the entire stream in a single request. Helper for :meth:`stream_file`: :type start: integer :param start: start byte of the range. """ self._ensure_initialized() if self.total_size is None: raise TransferInvalidError( 'Total size must be known for SendMediaBody') body_stream = StreamSlice(self.stream, self.total_size - start) request = Request(url=self.url, http_method='PUT', body=body_stream) request.headers['Content-Type'] = self.mime_type if start == self.total_size: # End of an upload with 0 bytes left to send; just finalize. range_string = 'bytes */%s' % self.total_size else: range_string = 'bytes %s-%s/%s' % (start, self.total_size - 1, self.total_size) request.headers['Content-Range'] = range_string return self._send_media_request(request, self.total_size)
def _send_chunk(self, start): """Send a chunk of the stream. Helper for :meth:`stream_file`: :type start: integer :param start: start byte of the range. :rtype: :class:`gcloud.streaming.http_wrapper.Response` :returns: The response from the chunked upload request. """ self._ensure_initialized() no_log_body = self.total_size is None if self.total_size is None: # For the streaming resumable case, we need to detect when # we're at the end of the stream. body_stream = BufferedStream(self.stream, start, self.chunksize) end = body_stream.stream_end_position if body_stream.stream_exhausted: self._total_size = end # Here, change body_stream from a stream to a string object, # which means reading a chunk into memory. This works around # https://code.google.com/p/httplib2/issues/detail?id=176 which can # cause httplib2 to skip bytes on 401's for file objects. body_stream = body_stream.read(self.chunksize) else: end = min(start + self.chunksize, self.total_size) body_stream = StreamSlice(self.stream, end - start) request = Request(url=self.url, http_method='PUT', body=body_stream) request.headers['Content-Type'] = self.mime_type if no_log_body: # Disable logging of streaming body. request.loggable_body = '<media body>' if self.total_size is None: # Streaming resumable upload case, unknown total size. range_string = 'bytes %s-%s/*' % (start, end - 1) elif end == start: # End of an upload with 0 bytes left to send; just finalize. range_string = 'bytes */%s' % self.total_size else: # Normal resumable upload case with known sizes. range_string = 'bytes %s-%s/%s' % (start, end - 1, self.total_size) request.headers['Content-Range'] = range_string return self._send_media_request(request, end)