How to copy InMemoryUploadedFile object to disk

I am trying to catch a file sent with form and perform some operations on it before it will be saved. So I need to create a copy of this file in temp directory, but I don’t know how to reach it. Shutil’s functions fail to copy this file, since there is no path to it. So is there a way to do this operation in some other way ?

My code :

    image = form.cleaned_data['image']
    temp = os.path.join(settings.PROJECT_PATH, 'tmp')
    sourceFile = image.name # without .name here it wasn't working either
    import shutil
    shutil.copy(sourceFile, temp)

Which raises :

Exception Type: IOError at /
Exception Value: (2, 'No such file or directory')

And the debug :

#  (..)views.py in function

  67. sourceFile = image.name
  68. import shutil
  69. shutil.copy2(sourceFile, temp) ...

# (..)Python26libshutil.py in copy2

  92. """Copy data and all stat info ("cp -p src dst").
  93.
  94. The destination may be a directory.
  95.
  96. """
  97. if os.path.isdir(dst):
  98. dst = os.path.join(dst, os.path.basename(src))  
  99. copyfile(src, dst) ... 
 100. copystat(src, dst)
 101.

▼ Local vars
Variable    Value
dst     
u'(..)\tmp\myfile.JPG'
src     
u'myfile.JPG'
# (..)Python26libshutil.py in copyfile

  45. """Copy data from src to dst"""
  46. if _samefile(src, dst):
  47. raise Error, "`%s` and `%s` are the same file" % (src, dst)
  48.
  49. fsrc = None
  50. fdst = None
  51. try:
  52. fsrc = open(src, 'rb') ...
  53. fdst = open(dst, 'wb')
  54. copyfileobj(fsrc, fdst)
  55. finally:
  56. if fdst:
  57. fdst.close()
  58. if fsrc:

▼ Local vars
Variable    Value
dst     
u'(..)\tmp\myfile.JPG'
fdst    
None
fsrc    
None
src     
u'myfile.JPG'

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

This is similar question, it might help.

import os
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.conf import settings

data = request.FILES['image'] # or self.files['image'] in your form

path = default_storage.save('tmp/somename.mp3', ContentFile(data.read()))
tmp_file = os.path.join(settings.MEDIA_ROOT, path)

Method 2

As mentioned by @Sławomir Lenart, when uploading large files, you don’t want to clog up system memory with a data.read().

From Django docs :

Looping over UploadedFile.chunks() instead of using read() ensures
that large files don’t overwhelm your system’s memory

from django.core.files.storage import default_storage

filename = "whatever.xyz" # received file name
file_obj = request.data['file']

with default_storage.open('tmp/'+filename, 'wb+') as destination:
    for chunk in file_obj.chunks():
        destination.write(chunk)

This will save the file at MEDIA_ROOT/tmp/ as your default_storage will unless told otherwise.

Method 3

Here is another way to do it with python’s mkstemp:

### get the inmemory file
data = request.FILES.get('file') # get the file from the curl

### write the data to a temp file
tup = tempfile.mkstemp() # make a tmp file
f = os.fdopen(tup[0], 'w') # open the tmp file for writing
f.write(data.read()) # write the tmp file
f.close()

### return the path of the file
filepath = tup[1] # get the filepath
return filepath

Method 4

Your best course of action is to write a custom Upload handler. See the docs . If you add a “file_complete” handler, you can access the file’s content regardless of having a memory file or a temp path file. You can also use the “receive_data_chunck” method and write your copy within it.

Regards

Method 5

This is how I tried to save the file locally

    file_object = request.FILES["document_file"]
    file_name = str(file_object)
    print(f'[INFO] File Name: {file_name}')
    with open(file_name, 'wb+') as f:
        for chunk in file_object.chunks():
            f.write(chunk)


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x