1

I have 2 ways to upload an image, one via files (image) and one via url (imageURL). If the user chooses url, I have a model method to download the file from the url:

class Post(models.Model):
    ...
    image = models.FileField(null=True, blank=True)
    imageURL = models.URLField(null=True, blank=True)

    def download_file_from_url(self):
        print('DOWNLOAD') #prints
        # Stream the image from the url
        try:
            request = requests.get(self, stream=True)
        except requests.exceptions.RequestException as e:
            # TODO: log error here
            return None

        if request.status_code != requests.codes.ok:
            # TODO: log error here
            return None

        # Create a temporary file
        lf = tempfile.NamedTemporaryFile()

        # Read the streamed image in sections
        for block in request.iter_content(1024 * 8):

            # If no more file then stop
            if not block:
                break

            # Write image block to temporary file
            lf.write(block)
            print('WRITE') #prints
            return files.File(lf)

views

def post(request):
    ... 
    if form_post.is_valid():
        instance = form_post.save(commit=False)

        if instance.imageURL:
            instance.image = Post.download_file_from_url(instance.imageURL)
            instance.save()

Uploading an image from file works fine..however when uploading via url, the model method returns this error:

SuspiciousFileOperation at /post/
The joined path (/var/folders/t9/7v8mki3s3h39fzylxfpsk9640000nn/T/tmpmvb9wxq6) is located outside of the base path component (/Users/zorgan/Desktop/app/draft1/media) 

Can someone explain what this means? It's obviously not uploading to the media folder, but I have no idea what /var/folders/ is. All my media files upload to the stardard media folder:

urls

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

settings

MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

and this works fine when uploading via files (image). It only returns the error when uploading via url imageURL. Any idea what the problem is?

Zorgan
  • 8,227
  • 23
  • 106
  • 207
  • I would guess it has to do with `tempfile.NamedTemporaryFile()` – TemporalWolf Apr 11 '17 at 22:19
  • Any idea what the problem would be? I put a print statement after `lf.write(block)` and it prints. – Zorgan Apr 11 '17 at 22:22
  • Have you tried http://stackoverflow.com/questions/22019371/django-how-to-allow-a-suspicious-file-operation-copy-a-file – TemporalWolf Apr 11 '17 at 22:44
  • Just going through it now, i'm not too sure how to implement that into my model function. Or do I just completely replace it? – Zorgan Apr 11 '17 at 22:51
  • Or you can pass the `NamedTemporaryFile(dir=some_django_folder)` so it stays inside the django media root. – TemporalWolf Apr 11 '17 at 22:53
  • Ok so i've just changed it to `lf = tempfile.NamedTemporaryFile(dir='media')` The image still isn't saving/rendering but this may be right, I just haven't put in the right value for `dir`. The GET request looks like this: `"GET /media/Users/zorgan/Desktop/app/draft1/media/tnpvh7vv7n8_JVCE3rr HTTP/1.1" 404 1972`. So it's putting the whole path again after `/media/`. Any idea? – Zorgan Apr 11 '17 at 23:06
  • If the absolute path doesn't work I dunno. – TemporalWolf Apr 11 '17 at 23:31
  • Why `image` is FileField and not ImageField and why doesn't it have `upload_to` handler? – Andrey Shipilov Apr 12 '17 at 04:19
  • Because `image` can also handle video uploads (I called it image because it could originally only handle images). And there is no `upload_to` because the upload location is already specified in my settings and urls (I pastes them in my edit) – Zorgan Apr 12 '17 at 04:38

0 Answers0