def _update_asset(request, course_key, asset_key): """ restful CRUD operations for a course asset. Currently only DELETE, POST, and PUT methods are implemented. asset_path_encoding: the odd /c4x/org/course/category/name repr of the asset (used by Backbone as the id) """ if request.method == 'DELETE': try: delete_asset(course_key, asset_key) return JsonResponse() except AssetNotFoundException: return JsonResponse(status=404) elif request.method in ('PUT', 'POST'): if 'file' in request.FILES: return _upload_asset(request, course_key) else: # Update existing asset try: modified_asset = json.loads(request.body) except ValueError: return HttpResponseBadRequest() contentstore().set_attr(asset_key, 'locked', modified_asset['locked']) # Delete the asset from the cache so we check the lock status the next time it is requested. del_cached_content(asset_key) return JsonResponse(modified_asset, status=201)
def delete_asset(course_key, asset_key): """ Deletes asset represented by given 'asset_key' in the course represented by given course_key. """ # Make sure the item to delete actually exists. try: content = contentstore().find(asset_key) except NotFoundError: raise AssetNotFoundException # ok, save the content into the trashcan contentstore('trashcan').save(content) # see if there is a thumbnail as well, if so move that as well if content.thumbnail_location is not None: # We are ignoring the value of the thumbnail_location-- we only care whether # or not a thumbnail has been stored, and we can now easily create the correct path. thumbnail_location = course_key.make_asset_key('thumbnail', asset_key.name) try: thumbnail_content = contentstore().find(thumbnail_location) contentstore('trashcan').save(thumbnail_content) # hard delete thumbnail from origin contentstore().delete(thumbnail_content.get_id()) # remove from any caching del_cached_content(thumbnail_location) except Exception: # pylint: disable=broad-except logging.warning('Could not delete thumbnail: %s', thumbnail_location) # delete the original contentstore().delete(content.get_id()) # remove from cache del_cached_content(content.location)
def test_delete(self): set_cached_content(self.mockAsset) del_cached_content(self.nonUnicodeLocation) self.assertEqual(None, get_cached_content(self.unicodeLocation), 'should not be stored in cache with unicodeLocation') self.assertEqual(None, get_cached_content(self.nonUnicodeLocation), 'should not be stored in cache with nonUnicodeLocation')
def test_delete(self): set_cached_content(self.mockAsset) del_cached_content(self.nonUnicodeLocation) self.assertEqual(None, get_cached_content(self.unicodeLocation), 'should not be stored in cache with unicodeLocation') self.assertEqual( None, get_cached_content(self.nonUnicodeLocation), 'should not be stored in cache with nonUnicodeLocation')
def _upload_file(subs_file, location, filename): mime_type = subs_file.content_type content_location = StaticContent.compute_location( location.course_key, filename ) content = StaticContent(content_location, filename, mime_type, subs_file.read()) contentstore().save(content) del_cached_content(content.location)
def _upload_file(subs_file, location, filename): mime_type = subs_file.content_type content_location = StaticContent.compute_location(location.course_key, filename) content = StaticContent(content_location, filename, mime_type, subs_file.read()) contentstore().save(content) del_cached_content(content.location)
def _clear_assets(location): """ Clear all assets for location. """ store = contentstore() assets, __ = store.get_all_content_for_course(location.course_key) for asset in assets: asset_location = asset['asset_key'] del_cached_content(asset_location) store.delete(asset_location)
def save_subs_to_store(self, subs, subs_id): """Save transcripts into `StaticContent`.""" filedata = json.dumps(subs, indent=2) mime_type = 'application/json' filename = 'subs_{0}.srt.sjson'.format(subs_id) content_location = StaticContent.compute_location(self.course.id, filename) content = StaticContent(content_location, filename, mime_type, filedata) contentstore().save(content) del_cached_content(content_location) return content_location
def save_subs_to_store(self, subs, subs_id): """Save transcripts into `StaticContent`.""" filedata = json.dumps(subs, indent=2) mime_type = 'application/json' filename = 'subs_{0}.srt.sjson'.format(subs_id) content_location = StaticContent.compute_location( self.course.id, filename) content = StaticContent(content_location, filename, mime_type, filedata) contentstore().save(content) del_cached_content(content_location) return content_location
def _upload_asset(request, course_key): ''' This method allows for POST uploading of files into the course asset library, which will be supported by GridFS in MongoDB. ''' # Does the course actually exist?!? Get anything from it to prove its # existence try: modulestore().get_course(course_key) except ItemNotFoundError: # no return it as a Bad Request response logging.error("Could not find course: %s", course_key) return HttpResponseBadRequest() # compute a 'filename' which is similar to the location formatting, we're # using the 'filename' nomenclature since we're using a FileSystem paradigm # here. We're just imposing the Location string formatting expectations to # keep things a bit more consistent upload_file = request.FILES['file'] filename = upload_file.name mime_type = upload_file.content_type size = get_file_size(upload_file) # If file is greater than a specified size, reject the upload # request and send a message to the user. Note that since # the front-end may batch large file uploads in smaller chunks, # we validate the file-size on the front-end in addition to # validating on the backend. (see cms/static/js/views/assets.js) max_file_size_in_bytes = settings.MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB * 1000 ** 2 if size > max_file_size_in_bytes: return JsonResponse({ 'error': _( 'File {filename} exceeds maximum size of ' '{size_mb} MB. Please follow the instructions here ' 'to upload a file elsewhere and link to it instead: ' '{faq_url}' ).format( filename=filename, size_mb=settings.MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB, faq_url=settings.MAX_ASSET_UPLOAD_FILE_SIZE_URL, ) }, status=413) content_loc = StaticContent.compute_location(course_key, filename) chunked = upload_file.multiple_chunks() sc_partial = partial(StaticContent, content_loc, filename, mime_type) if chunked: content = sc_partial(upload_file.chunks()) tempfile_path = upload_file.temporary_file_path() else: content = sc_partial(upload_file.read()) tempfile_path = None # first let's see if a thumbnail can be created (thumbnail_content, thumbnail_location) = contentstore().generate_thumbnail( content, tempfile_path=tempfile_path, ) # delete cached thumbnail even if one couldn't be created this time (else # the old thumbnail will continue to show) del_cached_content(thumbnail_location) # now store thumbnail location only if we could create it if thumbnail_content is not None: content.thumbnail_location = thumbnail_location # then commit the content contentstore().save(content) del_cached_content(content.location) # readback the saved content - we need the database timestamp readback = contentstore().find(content.location) locked = getattr(content, 'locked', False) response_payload = { 'asset': _get_asset_json( content.name, content.content_type, readback.last_modified_at, content.location, content.thumbnail_location, locked ), 'msg': _('Upload completed') } return JsonResponse(response_payload)
def _upload_asset(request, course_key): ''' This method allows for POST uploading of files into the course asset library, which will be supported by GridFS in MongoDB. ''' # Does the course actually exist?!? Get anything from it to prove its # existence try: modulestore().get_course(course_key) except ItemNotFoundError: # no return it as a Bad Request response logging.error("Could not find course: %s", course_key) return HttpResponseBadRequest() # compute a 'filename' which is similar to the location formatting, we're # using the 'filename' nomenclature since we're using a FileSystem paradigm # here. We're just imposing the Location string formatting expectations to # keep things a bit more consistent upload_file = request.FILES['file'] filename = upload_file.name mime_type = upload_file.content_type size = get_file_size(upload_file) # If file is greater than a specified size, reject the upload # request and send a message to the user. Note that since # the front-end may batch large file uploads in smaller chunks, # we validate the file-size on the front-end in addition to # validating on the backend. (see cms/static/js/views/assets.js) max_file_size_in_bytes = settings.MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB * 1000**2 if size > max_file_size_in_bytes: return JsonResponse( { 'error': _('File {filename} exceeds maximum size of ' '{size_mb} MB. Please follow the instructions here ' 'to upload a file elsewhere and link to it instead: ' '{faq_url}').format( filename=filename, size_mb=settings.MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB, faq_url=settings.MAX_ASSET_UPLOAD_FILE_SIZE_URL, ) }, status=413) content_loc = StaticContent.compute_location(course_key, filename) chunked = upload_file.multiple_chunks() sc_partial = partial(StaticContent, content_loc, filename, mime_type) if chunked: content = sc_partial(upload_file.chunks()) tempfile_path = upload_file.temporary_file_path() else: content = sc_partial(upload_file.read()) tempfile_path = None # first let's see if a thumbnail can be created (thumbnail_content, thumbnail_location) = contentstore().generate_thumbnail( content, tempfile_path=tempfile_path, ) # delete cached thumbnail even if one couldn't be created this time (else # the old thumbnail will continue to show) del_cached_content(thumbnail_location) # now store thumbnail location only if we could create it if thumbnail_content is not None: content.thumbnail_location = thumbnail_location # then commit the content contentstore().save(content) del_cached_content(content.location) # readback the saved content - we need the database timestamp readback = contentstore().find(content.location) locked = getattr(content, 'locked', False) response_payload = { 'asset': _get_asset_json(content.name, content.content_type, readback.last_modified_at, content.location, content.thumbnail_location, locked), 'msg': _('Upload completed') } return JsonResponse(response_payload)