예제 #1
0
    def __SendMediaBody(self, start, additional_headers=None):
        """Send the entire media stream in a single request."""
        self.EnsureInitialized()
        if self.total_size is None:
            raise exceptions.TransferInvalidError(
                'Total size must be known for SendMediaBody')
        body_stream = stream_slice.StreamSlice(self.stream,
                                               self.total_size - start)

        request = http_wrapper.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
        if additional_headers:
            request.headers.update(additional_headers)

        return self.__SendMediaRequest(request, self.total_size)
 def __NormalizeStartEnd(self, start, end=None):
     if end is not None:
         if start < 0:
             raise exceptions.TransferInvalidError(
                 'Cannot have end index with negative start index')
         elif start >= self.total_size:
             raise exceptions.TransferInvalidError(
                 'Cannot have start index greater than total size')
         end = min(end, self.total_size - 1)
         if end < start:
             raise exceptions.TransferInvalidError(
                 'Range requested with end[%s] < start[%s]' % (end, start))
         return start, end
     else:
         if start < 0:
             start = max(0, start + self.total_size)
         return start, self.total_size
예제 #3
0
 def read(self, size=None):
     if size is not None:
         size = min(size, self.__remaining_bytes)
     else:
         size = self.__remaining_bytes
     data = self.__stream.read(size)
     if not data and self.__remaining_bytes:
         raise exceptions.TransferInvalidError(
             'Not enough bytes in stream; expected %d, stream exhasted after %d'
             % (self.__max_bytes, self.__remaining_bytes))
     self.__remaining_bytes -= len(data)
     return data
예제 #4
0
 def __StreamMedia(self,
                   callback=None,
                   finish_callback=None,
                   additional_headers=None,
                   use_chunks=True):
     """Helper function for StreamMedia / StreamInChunks."""
     if self.strategy != RESUMABLE_UPLOAD:
         raise exceptions.InvalidUserInputError(
             'Cannot stream non-resumable upload')
     callback = callback or self._ArgPrinter
     finish_callback = finish_callback or self._CompletePrinter
     # final_response is set if we resumed an already-completed upload.
     response = self.__final_response
     send_func = self.__SendChunk if use_chunks else self.__SendMediaBody
     if use_chunks:
         self.__ValidateChunksize(self.chunksize)
     self.EnsureInitialized()
     while not self.complete:
         response = send_func(self.stream.tell(),
                              additional_headers=additional_headers)
         if response.status_code in (httplib.OK, httplib.CREATED):
             self.__complete = True
             break
         self.__progress = self.__GetLastByte(response.info['range'])
         if self.progress + 1 != self.stream.tell():
             # TODO: Add a better way to recover here.
             raise exceptions.CommunicationError(
                 'Failed to transfer all bytes in chunk, upload paused at byte '
                 '%d' % self.progress)
         self._ExecuteCallback(callback, response)
     if self.__complete:
         # TODO: Decide how to handle errors in the non-seekable case.
         current_pos = self.stream.tell()
         self.stream.seek(0, os.SEEK_END)
         end_pos = self.stream.tell()
         self.stream.seek(current_pos)
         if current_pos != end_pos:
             raise exceptions.TransferInvalidError(
                 'Upload complete with %s additional bytes left in stream' %
                 (long(end_pos) - long(current_pos)))
     self._ExecuteCallback(finish_callback, response)
     return response
 def EnsureUninitialized(self):
     if self.initialized:
         raise exceptions.TransferInvalidError('Cannot re-initialize %s',
                                               self._type_name)
 def EnsureInitialized(self):
     if not self.initialized:
         raise exceptions.TransferInvalidError(
             'Cannot use uninitialized %s', self._type_name)