Hi Florian,
Thanks for helping out. I see that my path is not relative to my upload_to so based on what you write, that makes sense. The upload to is left over from earlier iterations of my code. There is a requirement that images be uploaded to AWS in a human friendly directory structure. In my code example below I demonstrate where the file path comes from.
The stacktrace is:
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py" line 181 in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/decorators/csrf.py" line 54 in wrapped_view
return view_func(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py" line 70 in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py" line 509 in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py" line 469 in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py" line 480 in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py" line 506 in dispatch
response = handler(request, *args, **kwargs)
File "/code/media/views.py", line 106 in post [args] [locals]
instance = self.create_media(
File "/code/media/views.py", line 142 in create_media [args] [locals]
instance.file.save(filename, file)
- 3 non-project frames
File "/usr/local/lib/python3.8/site-packages/django/db/models/fields/files.py" line 88 in save
name = self.field.generate_filename(self.instance, name)
File "/usr/local/lib/python3.8/site-packages/django/db/models/fields/files.py" line 321 in generate_filename
filename = validate_file_name(filename, allow_relative_path=True)
File "/usr/local/lib/python3.8/site-packages/django/core/files/utils.py" line 18 in validate_file_name [args] [locals]
raise SuspiciousFileOperation(
SuspiciousFileOperation: Detected path traversal attempt in '/case_data/dogs/01000/dogs_1000_1622660073141.jpeg'
The final URL is:
https://my-bucket.s3.amazonaws.com/case_data/dogs/01000/dogs_1000_1622660073141.jpeg
I’ve added some more context to my code below.
class MediaUploadSerializer(serializers.Serializer):
filename = serializers.CharField(max_length=64, min_length=1, required=True)
short_name = serializers.CharField(max_length=64, min_length=1, required=True)
annotation = serializers.CharField(max_length=1024, min_length=1, required=False)
file = serializers.FileField(required=True)
case = serializers.UUIDField(required=True)
class MediaCreatorView(views.APIView):
serializer_class = serializers.MediaUploadSerializer
model = # in this instance it an Image as in show in my first post
def post(self, request, *args, **kwargs):
# ...
file = request.FILES["file"] # FileField
filename = serializer.validated_data.get("filename", None) # CharField
# ..
# the below returns the path of where the file is stored on AWS.
# this results in the string:
# "/case_data/dogs/01000/dogs_1000_1622660073141.jpeg"
filename = utils.aws_filename_key(group, case) + filename
try:
instance = self.create_media(
file, filename, request.user, short_name=short_name, annotation=annotation
)
# ...
def create_media(self, file, filename, user, short_name=None, annotation=None):
try:
instance = self.model(
file=filename, uploaded_by=user, short_name=short_name, annotation=annotation
)
instance.save()
instance.file.save(filename, file)
return instance
except IntegrityError:
If I have understood the problem correctly, I will need to have my file path relative to upload_to=images. Therefore I should have:
images/case_data/dogs/01000/dogs_1000_1622660073141.jpeg
instead of
/case_data/dogs/01000/dogs_1000_1622660073141.jpeg
As a test, I modified my aws key generating code to this:
filename = "images" + utils.aws_filename_key(group, case) + filename
# filename now equals: "images/case_data/dogs/01000/dogs_1000_1622660073141.jpeg"
With this small hack, I can now upload my images using 3.2.4.
Have I understood you correctly or am I still off in la la land?
Cheers,
Conor