@access.user
    @describeRoute(
        Description('Upload a chunk of a file with multipart/form-data.')
        .consumes('multipart/form-data')
        .param('uploadId', 'The ID of the upload record.', paramType='form')
        .param('offset', 'Offset of the chunk in the file.', dataType='integer',
               paramType='form')
        .param('chunk', 'The actual bytes of the chunk. For external upload '
               'behaviors, this may be set to an opaque string that will be '
               'handled by the assetstore adapter.',
               dataType='File', paramType='body')
        .errorResponse('ID was invalid.')
        .errorResponse('Received too many bytes.')
        .errorResponse('Chunk is smaller than the minimum size.')
        .errorResponse('You are not the user who initiated the upload.', 403)
        .errorResponse('Failed to store upload.', 500)
    )
    def readChunk(self, params):
        """
        After the temporary upload record has been created (see initUpload),
        the bytes themselves should be passed up in ordered chunks. The user
        must remain logged in when passing each chunk, to authenticate that
        the writer of the chunk is the same as the person who initiated the
        upload. The passed offset is a verification mechanism for ensuring the
        server and client agree on the number of bytes sent/received.
        """
        self.requireParams(('offset', 'uploadId', 'chunk'), params)

        user = self.getCurrentUser()
        upload = self.model('upload').load(params['uploadId'], exc=True)
        offset = int(params['offset'])
        chunk = params['chunk']

        if upload['userId'] != user['_id']:
            raise AccessException('You did not initiate this upload.')

        if upload['received'] != offset:
            raise RestException(
                'Server has received %s bytes, but client sent offset %s.' % (
                    upload['received'], offset))
        try:
            if isinstance(chunk, cherrypy._cpreqbody.Part):
                return self.model('upload').handleChunk(upload, chunk.file)
            else:
                return self.model('upload').handleChunk(upload, chunk)
        except __HOLE__ as exc:
            if exc.errno == errno.EACCES:
                raise Exception('Failed to store upload.')
            raise
dataset/ETHPy150Open girder/girder/girder/api/v1/file.py/File.readChunk