Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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) ...  # (..)\Python26\lib\shutil.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' # (..)\Python26\lib\shutil.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' 
like image 887
sasklacz Avatar asked Sep 13 '10 16:09

sasklacz


2 Answers

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) 
like image 50
Davor Lucic Avatar answered Sep 19 '22 17:09

Davor Lucic


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.

like image 37
Emile Bergeron Avatar answered Sep 21 '22 17:09

Emile Bergeron