Django Directory Upload Get Sub-directory Names
Solution 1:
I believe this is how Django is implemented. Please refer to Django's Upload Handler doc.
It has its default upload handlers MemoryFileUploadHandler
and TemporaryFileUploadHandler
. Both of them are using the UploadedFile
for handling the files, and it has a function _set_name
, which takes the base name of the file.
Even there is a comment saying why it takes the basename:
def_set_name(self, name):
# Sanitize the file name so that it can't be dangerous.if name isnotNone:
# Just use the basename of the file -- anything else is dangerous.
name = os.path.basename(name)
# File names longer than 255 characters can cause problems on older OSes.iflen(name) > 255:
name, ext = os.path.splitext(name)
ext = ext[:255]
name = name[:255 - len(ext)] + ext
self._name = name
But I think you can can write your own upload handler which doesn't take the basename and behaves as you want. Here is little info how you can write custom upload handler.
Then you need to define your handler in FILE_UPLOAD_HANDLERS
setting.
EDITCustom Upload Handlers with Django 3.1
Solution 2:
Expanding on the previous answer, one way of getting the full path from a directory upload is by replacing slashes (\
and /
) in the file path (which get sanitized away) with hyphens:
classCustomMemoryFileUploadHandler(MemoryFileUploadHandler):defnew_file(self, *args, **kwargs):
args = (args[0], args[1].replace('/', '-').replace('\\', '-')) + args[2:]
super(CustomMemoryFileUploadHandler, self).new_file(*args, **kwargs)
classCustomTemporaryFileUploadHandler(TemporaryFileUploadHandler):defnew_file(self, *args, **kwargs):
args = (args[0], args[1].replace('/', '-').replace('\\', '-')) + args[2:]
super(CustomTemporaryFileUploadHandler, self).new_file(*args, **kwargs)
@csrf_exemptdefmy_view(request):
# replace upload handlers. This depends on FILE_UPLOAD_HANDLERS setting. Below code handles the default in Django 1.10
request.upload_handlers = [CustomMemoryFileUploadHandler(request), CustomTemporaryFileUploadHandler(request)]
return _my_view(request)
@csrf_protectdef_my_view(request):
# if the path of the uploaded file was "test/abc.jpg", here it will be "test-abc.jpg"
blah = request.FILES[0].name
Solution 3:
In addition to the previous answers there is another way which may be useful to someone.
You can get the original filename as it is in the multipart/form-data
payload without overriding handlers if you have only one file in the requests.
MemoryFileUploadHandler
and TemporaryFileUploadHandler
(which are used by default, see Django's docs: Built-in upload handlers) are inherited from the FileUploadHandler
class. Such objects have the file_name
variable (see Django's code). The full name of one of the files from the request is stored here (any one file, we can not say in advance). But if you always have one file in the request - this is the way.
So the view will look like:
def your_view(request):
file = request.FILES.get('file_field')
full_file_name = request.upload_handlers[0].file_name # e.g. 'MainDir/SubDir1/1.jpg'
For multiple file upload we can override handlers:
classNamedMemoryFileUploadHandler(MemoryFileUploadHandler):
deffile_complete(self, file_size):
in_memory_file = super().file_complete(file_size)
if in_memory_file isNone:
returnreturn in_memory_file, self.file_name
classNamedTemporaryFileUploadHandler(TemporaryFileUploadHandler):
deffile_complete(self, file_size):
temporary_file = super().file_complete(file_size)
if temporary_file isNone:
returnreturn temporary_file, self.file_name
@csrf_exemptdefupload_files(request):
request.upload_handlers = [
NamedMemoryFileUploadHandler(request),
NamedTemporaryFileUploadHandler(request),
]
return _upload_files(request)
@csrf_protectdef_upload_files(request):
files = request.FILES.getlist("file") # list of tuples [(<file1>, "'MainDir/SubDir1/1.jpg'"), (<file2>, "'MainDir/SubDir2/2.jpg'")]for tmp_file, full_path in files:
...
Post a Comment for "Django Directory Upload Get Sub-directory Names"