def setUp(self): self.upload_id = _get_file_id() self.file_id = _get_file_id() self.file_content = ('This is some test file data for an ' 'uploaded file.') self.fn = 'my_test_file.txt' uploaded_file = SimpleUploadedFile(self.fn, str.encode(self.file_content)) tu = TemporaryUpload(upload_id=self.upload_id, file_id=self.file_id, file=uploaded_file, upload_name=self.fn, upload_type=TemporaryUpload.FILE_DATA) tu.save()
def handle_upload(self, request, upload_id, file_id): # Since the upload_id and file_id are being provided here as # parameters, we check that they are valid. This should be done by # the DB and an error would be generated in the tu.save() call below # however SQLite doesn't handle field length validation so this won't # be picked up when using SQLite. if ((not self._file_id_valid(file_id)) or (not self._upload_id_valid(upload_id))): return Response('Invalid ID for handling upload.', content_type='text/plain', status=status.HTTP_500_INTERNAL_SERVER_ERROR) file_obj = self._get_file_obj(request) # The type of parsed data should be a descendant of an UploadedFile # type. if not isinstance(file_obj, UploadedFile): raise ParseError('Invalid data type has been parsed.') # Save original file name and set name of saved file to the unique ID upload_filename = file_obj.name file_obj.name = file_id # Before we attempt to save the file, make sure that the upload # directory we're going to save to exists. # *** It's not necessary to explicitly create the directory since # *** the FileSystemStorage object creates the directory on save # if not os.path.exists(storage.location): # LOG.debug('Filepond app: Creating file upload directory ' # '<%s>...' % storage.location) # os.makedirs(storage.location, mode=0o700) LOG.debug('About to store uploaded temp file with filename: %s' % (upload_filename)) # We now need to create the temporary upload object and store the # file and metadata. tu = TemporaryUpload(upload_id=upload_id, file_id=file_id, file=file_obj, upload_name=upload_filename, upload_type=TemporaryUpload.FILE_DATA, uploaded_by=_get_user(request)) tu.save() response = Response(upload_id, status=status.HTTP_200_OK, content_type='text/plain') return response
def setUp(self): # Set up an initial file upload self.upload_id = _get_file_id() self.upload_id2 = _get_file_id() self.file_id = _get_file_id() self.file_content = ('This is some test file data for an ' 'uploaded file.') self.fn = 'my_test_file.txt' self.test_target_dirname = 'test_storage/' self.test_target_filename = '/test_storage/testfile.txt' self.test_target_filename2 = '/test_storage/testfile2.txt' uploaded_file = SimpleUploadedFile(self.fn, str.encode(self.file_content)) tu = TemporaryUpload(upload_id=self.upload_id, file_id=self.file_id, file=uploaded_file, upload_name=self.fn, upload_type=TemporaryUpload.FILE_DATA) tu.save() tu2 = TemporaryUpload(upload_id=self.upload_id2, file_id=self.file_id, file=uploaded_file, upload_name=self.fn, upload_type=TemporaryUpload.FILE_DATA) tu2.save()
def setUp(self): global store_upload # Set storage backend to sftp storage local_settings.STORAGES_BACKEND = \ 'storages.backends.sftpstorage.SFTPStorage' # Setting up a mock for the storage backend based on examples at # https://docs.python.org/3.7/library/unittest.mock-examples.html# \ # applying-the-same-patch-to-every-test-method patcher = patch('storages.backends.sftpstorage.SFTPStorage') patcher.start() self.addCleanup(patcher.stop) # Mock the temporary storage object so that we're not unnecessarily # saving files to the local file system. patcher2 = patch('django.core.files.storage.FileSystemStorage') patcher2.start() self.addCleanup(patcher2.stop) # Reinitialse stored upload after we changed the STORAGES_BACKEND # class name above. This ensures that we're looking at the mocked # backend class. import django_drf_filepond.api self.api = django_drf_filepond.api django_drf_filepond.api.storage_backend_initialised = False django_drf_filepond.api._init_storage_backend() self.mock_storage_backend = django_drf_filepond.api.storage_backend store_upload = django_drf_filepond.api.store_upload # Check that we're using a mocked storage backend self.assertTrue( isinstance(django_drf_filepond.api.storage_backend, MagicMock), ('The created storage backend should be mocked but it is not of ' 'type unittest.mock.MagicMock...')) # Set up an initial file upload self.upload_id = _get_file_id() self.upload_id2 = _get_file_id() self.file_id = _get_file_id() self.file_content = ('This is some test file data for an ' 'uploaded file.') self.fn = 'my_test_file.txt' self.test_target_filename = '/test_storage/testfile.txt' self.test_target_filename2 = '/test_storage/testfile2.txt' uploaded_file = MagicMock(spec=SimpleUploadedFile) uploaded_file.name = self.fn tu = TemporaryUpload(upload_id=self.upload_id, file_id=self.file_id, file=uploaded_file, upload_name=self.fn, upload_type=TemporaryUpload.FILE_DATA) tu.save() tu2 = TemporaryUpload(upload_id=self.upload_id2, file_id=self.file_id, file=uploaded_file, upload_name=self.fn, upload_type=TemporaryUpload.FILE_DATA) tu2.save()
def _store_upload(self, tuc): if not tuc.upload_complete: LOG.error('Attempt to store an incomplete upload with ID <%s>' % (tuc.upload_id)) raise ValueError('Attempt to store an incomplete upload with ID ' '<%s>' % (tuc.upload_id)) # Load each of the file parts into a BytesIO object and store them # via a TemporaryUpload object. chunk_dir = os.path.join(storage.base_location, tuc.upload_dir) file_data = BytesIO() for i in range(1, tuc.last_chunk + 1): chunk_file = os.path.join(chunk_dir, '%s_%s' % (tuc.file_id, i)) if not os.path.exists(chunk_file): raise FileNotFoundError('Chunk file not found for chunk <%s>' % (i)) with open(chunk_file, 'rb') as cf: file_data.write(cf.read()) # Prepare an InMemoryUploadedFile object so that the data can be # successfully saved via the FileField in the TemporaryUpload object memfile = InMemoryUploadedFile(file_data, None, tuc.file_id, 'application/octet-stream', tuc.total_size, None) tu = TemporaryUpload(upload_id=tuc.upload_id, file_id=tuc.file_id, file=memfile, upload_name=tuc.upload_name, upload_type=TemporaryUpload.FILE_DATA, uploaded_by=tuc.uploaded_by) tu.save() # Check that the final file is stored and of the correct size stored_file_path = os.path.join(chunk_dir, tuc.file_id) if ((not os.path.exists(stored_file_path)) or (not os.path.getsize(stored_file_path) == tuc.total_size)): raise ValueError('Stored file size wrong or file not found.') LOG.debug('Full file built from chunks and saved. Deleting chunks ' 'and TemporaryUploadChunked object.') for i in range(1, tuc.last_chunk + 1): chunk_file = os.path.join(chunk_dir, '%s_%s' % (tuc.file_id, i)) os.remove(chunk_file) tuc.delete()
def setUp(self): # Set up an initial file upload self.upload_id = _get_file_id() self.file_id = _get_file_id() self.file_content = ('This is some test file data for an ' 'uploaded file.') self.fn = 'my_test_file.txt' self.test_filename = 'sdf5dua32defh754dhsrr2' uploaded_file = SimpleUploadedFile(self.fn, str.encode(self.file_content)) tu = TemporaryUpload(upload_id=self.upload_id, file_id=self.file_id, file=uploaded_file, upload_name=self.fn, upload_type=TemporaryUpload.FILE_DATA) tu.save() # Now set up a stored version of this upload su = StoredUpload(upload_id=self.upload_id, file_path=('%s' % (self.fn)), uploaded=tu.uploaded) su.save()
def head(self, request): LOG.debug('Filepond API: Fetch view HEAD called...') result = self._process_request(request) if isinstance(result, tuple): buf, file_id, upload_file_name, content_type = result elif isinstance(result, Response): return result else: raise ValueError('process_request result is of an unexpected type') file_size = buf.seek(0, os.SEEK_END) buf.seek(0) # The addressing of filepond issue #154 # (https://github.com/pqina/filepond/issues/154) means that fetch # can now store a file downloaded from a remote URL and return file # metadata in the header if a HEAD request is received. If we get a # GET request then the standard approach of proxying the file back # to the client is used. upload_id = _get_file_id() memfile = InMemoryUploadedFile(buf, None, file_id, content_type, file_size, None) tu = TemporaryUpload(upload_id=upload_id, file_id=file_id, file=memfile, upload_name=upload_file_name, upload_type=TemporaryUpload.URL, uploaded_by=_get_user(request)) tu.save() response = Response(status=status.HTTP_200_OK) response['Content-Type'] = content_type response['Content-Length'] = file_size response['X-Content-Transfer-Id'] = upload_id response['Content-Disposition'] = ('inline; filename=%s' % upload_file_name) return response
def post(self, request): LOG.debug('Filepond API: Process view POST called...') # Enforce that the upload location must be a sub-directory of # the project base directory # TODO: Check whether this is necessary - maybe add a security # parameter that can be disabled to turn off this check if the # developer wishes? if ((not hasattr(local_settings, 'UPLOAD_TMP')) or (not (storage.location).startswith(local_settings.BASE_DIR))): return Response( 'The file upload path settings are not ' 'configured correctly.', status=status.HTTP_500_INTERNAL_SERVER_ERROR) # Check that we've received a file and then generate a unique ID # for it. Also generate a unique UD for the temp upload dir file_id = _get_file_id() upload_id = _get_file_id() # By default the upload element name is expected to be "filepond" # As raised in issue #4, there are cases where there may be more # than one filepond instance on a page, or the developer has opted # not to use the name "filepond" for the filepond instance. # Using the example from #4, this provides support these cases. upload_field_name = 'filepond' if 'fp_upload_field' in request.data: upload_field_name = request.data['fp_upload_field'] if upload_field_name not in request.data: raise ParseError("Invalid request data has been provided.") file_obj = request.data[upload_field_name] # Save original file name and set name of saved file to the unique ID upload_filename = file_obj.name file_obj.name = file_id # The type of parsed data should be a descendant of an UploadedFile # type. if not isinstance(file_obj, UploadedFile): raise ParseError('Invalid data type has been parsed.') # Before we attempt to save the file, make sure that the upload # directory we're going to save to exists. # *** It's not necessary to explicitly create the directory since # *** the FileSystemStorage object creates the directory on save # if not os.path.exists(storage.location): # LOG.debug('Filepond app: Creating file upload directory ' # '<%s>...' % storage.location) # os.makedirs(storage.location, mode=0o700) # We now need to create the temporary upload object and store the # file and metadata. tu = TemporaryUpload(upload_id=upload_id, file_id=file_id, file=file_obj, upload_name=upload_filename, upload_type=TemporaryUpload.FILE_DATA) tu.save() response = Response(upload_id, status=status.HTTP_200_OK, content_type='text/plain') return response