Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
3aaa2868
Commit
3aaa2868
authored
Aug 14, 2013
by
Julian Arni
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Process uploaded chunks.
Also adds lockfile for asynchronous status updates.
parent
50934d4d
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
95 additions
and
41 deletions
+95
-41
cms/djangoapps/contentstore/views/assets.py
+95
-41
No files found.
cms/djangoapps/contentstore/views/assets.py
View file @
3aaa2868
...
...
@@ -4,6 +4,7 @@ import os
import
tarfile
import
shutil
import
cgi
import
re
from
functools
import
partial
from
tempfile
import
mkdtemp
from
path
import
path
...
...
@@ -38,6 +39,9 @@ from util.json_request import JsonResponse
__all__
=
[
'asset_index'
,
'upload_asset'
,
'import_course'
,
'generate_export_course'
,
'export_course'
]
MAX_UP_LENGTH
=
20000352
CONTENT_RE
=
re
.
compile
(
r"(?P<start>\d{1,11})-(?P<stop>\d{1,11})/(?P<end>\d{1,11})"
)
def
assets_to_json_dict
(
assets
):
"""
...
...
@@ -265,70 +269,120 @@ def remove_asset(request, org, course, name):
@login_required
def
import_course
(
request
,
org
,
course
,
name
):
"""
This method will handle a POST request to upload and import a .tar.gz file into a specified course
This method will handle a POST request to upload and import a .tar.gz file
into a specified course
"""
location
=
get_location_and_verify_access
(
request
,
org
,
course
,
name
)
if
request
.
method
in
(
'POST'
,
'PUT'
):
filename
=
request
.
FILES
[
'course-data'
]
.
name
if
not
filename
.
endswith
(
'.tar.gz'
):
return
HttpResponse
(
json
.
dumps
({
'ErrMsg'
:
'We only support uploading a .tar.gz file.'
}))
if
request
.
method
==
'POST'
:
data_root
=
path
(
settings
.
GITHUB_REPO_ROOT
)
course_subdir
=
"{0}-{1}-{2}"
.
format
(
org
,
course
,
name
)
course_dir
=
data_root
/
course_subdir
if
not
course_dir
.
isdir
():
os
.
mkdir
(
course_dir
)
filename
=
request
.
FILES
[
'course-data'
]
.
name
if
not
filename
.
endswith
(
'.tar.gz'
):
return
HttpResponse
(
json
.
dumps
({
'ErrMsg'
:
'We only support uploading a .tar.gz file.'
}))
temp_filepath
=
course_dir
/
filename
if
not
course_dir
.
isdir
():
os
.
mkdir
(
course_dir
)
logging
.
debug
(
'importing course to {0}'
.
format
(
temp_filepath
))
# Get upload chunks byte ranges
matches
=
CONTENT_RE
.
search
(
request
.
META
[
"HTTP_CONTENT_RANGE"
])
content_range
=
matches
.
groupdict
()
# stream out the uploaded files in chunks to disk
temp_file
=
open
(
temp_filepath
,
'wb+'
)
if
int
(
content_range
[
'start'
])
==
0
:
temp_file
=
open
(
temp_filepath
,
'wb+'
)
else
:
temp_file
=
open
(
temp_filepath
,
'ab+'
)
for
chunk
in
request
.
FILES
[
'course-data'
]
.
chunks
():
temp_file
.
write
(
chunk
)
temp_file
.
close
()
tar_file
=
tarfile
.
open
(
temp_filepath
)
tar_file
.
extractall
(
course_dir
+
'/'
)
# find the 'course.xml' file
dirpath
=
None
for
dirpath
,
_dirnames
,
filenames
in
os
.
walk
(
course_dir
):
for
filename
in
filenames
:
if
filename
==
'course.xml'
:
size
=
os
.
path
.
getsize
(
temp_filepath
)
if
int
(
content_range
[
'stop'
])
!=
int
(
content_range
[
'end'
])
-
1
:
# More chunks coming
return
JsonResponse
({
"files"
:
[{
"name"
:
filename
,
"size"
:
size
,
"deleteUrl"
:
""
,
"deleteType"
:
""
,
"url"
:
reverse
(
'import_course'
,
kwargs
=
{
'org'
:
location
.
org
,
'course'
:
location
.
course
,
'name'
:
location
.
name
}),
"thumbnailUrl"
:
""
}]
})
else
:
#This was the last chunk.
# 'Lock' with status info.
lock_filepath
=
data_root
/
(
filename
+
".lock"
)
with
open
(
lock_filepath
,
'w+'
)
as
lf
:
lf
.
write
(
"Extracting"
)
tar_file
=
tarfile
.
open
(
temp_filepath
)
tar_file
.
extractall
(
course_dir
+
'/'
)
with
open
(
lock_filepath
,
'w+'
)
as
lf
:
lf
.
write
(
"Verifying"
)
# find the 'course.xml' file
dirpath
=
None
for
dirpath
,
_dirnames
,
filenames
in
os
.
walk
(
course_dir
):
for
fname
in
filenames
:
if
fname
==
'course.xml'
:
break
if
fname
==
'course.xml'
:
break
if
filename
==
'course.xml'
:
break
if
filename
!=
'course.xml'
:
return
HttpResponse
(
json
.
dumps
({
'ErrMsg'
:
'Could not find the course.xml file in the package.'
}))
logging
.
debug
(
'found course.xml at {0}'
.
format
(
dirpath
))
if
dirpath
!=
course_dir
:
for
fname
in
os
.
listdir
(
dirpath
):
shutil
.
move
(
dirpath
/
fname
,
course_dir
)
if
fname
!=
'course.xml'
:
return
HttpResponse
(
json
.
dumps
({
'ErrMsg'
:
'Could not find the course.xml file in the package.'
}))
logging
.
debug
(
'found course.xml at {0}'
.
format
(
dirpath
))
if
dirpath
!=
course_dir
:
for
fname
in
os
.
listdir
(
dirpath
):
shutil
.
move
(
dirpath
/
fname
,
course_dir
)
_module_store
,
course_items
=
import_from_xml
(
modulestore
(
'direct'
),
settings
.
GITHUB_REPO_ROOT
,
[
course_subdir
],
load_error_modules
=
False
,
static_content_store
=
contentstore
(),
target_location_namespace
=
location
,
draft_store
=
modulestore
()
)
_module_store
,
course_items
=
import_from_xml
(
modulestore
(
'direct'
),
settings
.
GITHUB_REPO_ROOT
,
[
course_subdir
],
load_error_modules
=
False
,
static_content_store
=
contentstore
(),
target_location_namespace
=
location
,
draft_store
=
modulestore
())
# we can blow this away when we're done importing.
shutil
.
rmtree
(
course_dir
)
# we can blow this away when we're done importing.
shutil
.
rmtree
(
course_dir
)
logging
.
debug
(
'new course at {0}'
.
format
(
course_items
[
0
]
.
location
))
logging
.
debug
(
'new course at {0}'
.
format
(
course_items
[
0
]
.
location
))
with
open
(
lock_filepath
,
'w'
)
as
lf
:
lf
.
write
(
"Updating course"
)
create_all_course_groups
(
request
.
user
,
course_items
[
0
]
.
location
)
create_all_course_groups
(
request
.
user
,
course_items
[
0
]
.
location
)
logging
.
debug
(
'created all course groups at {0}'
.
format
(
course_items
[
0
]
.
location
))
logging
.
debug
(
'created all course groups at {0}'
.
format
(
course_items
[
0
]
.
location
)
)
os
.
remove
(
lock_filepath
)
return
HttpResponse
(
json
.
dumps
({
'Status'
:
'OK'
}))
return
HttpResponse
(
json
.
dumps
({
'Status'
:
'OK'
}))
else
:
course_module
=
modulestore
()
.
get_item
(
location
)
...
...
@@ -346,8 +400,8 @@ def import_course(request, org, course, name):
@login_required
def
generate_export_course
(
request
,
org
,
course
,
name
):
"""
This method will serialize out a course to a .tar.gz file which contains a
XML-based representation of
the course
This method will serialize out a course to a .tar.gz file which contains a
XML-based representation of
the course
"""
location
=
get_location_and_verify_access
(
request
,
org
,
course
,
name
)
course_module
=
modulestore
()
.
get_instance
(
location
.
course_id
,
location
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment