Wie InMemoryUploadedFile Objekt auf der Festplatte kopieren
-
02-10-2019 - |
Frage
Ich versuche, eine Datei abgeschickt mit Form zu fangen und einige Operationen darauf ausführen, bevor sie gespeichert werden. Also brauche ich eine Kopie dieser Datei in temp-Verzeichnis zu erstellen, aber ich weiß nicht, wie es zu erreichen. Shutil Funktionen versagen diese Datei zu kopieren, da es keinen Weg zu ihm. So ist es eine Möglichkeit, diesen Vorgang in einer anderen Art und Weise zu tun?
Mein 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)
Welche aufwirft:
Exception Type: IOError at /
Exception Value: (2, 'No such file or directory')
Und die 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'
Lösung
Diese ist ähnlich Frage, es könnte Hilfe.
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)
Andere Tipps
Wie bereits erwähnt von @ups wenn große Dateien hochladen, können Sie nicht wollen, Systemspeicher mit einem data.read()
verstopfen.
über
überwältigen, dass große DateienUploadedFile.chunks()
Looping statt mitread()
sicher nicht den Speicher Ihres Systems
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)
Dies wird die Datei auf MEDIA_ROOT/tmp/
speichern als default_storage
, wenn nichts anderes gesagt wird.
Ihre beste Vorgehensweise ist es, einen benutzerdefinierten Upload-Handler zu schreiben. Siehe docs . Wenn Sie einen „file_complete“ Handler hinzufügen, können Sie den Inhalt der Datei unabhängig von Zugriff auf eine Speicherdatei oder eine temporäre Pfaddatei mit. Sie können auch die „receive_data_chunck“ Methode verwenden, und Ihre Kopie in sie schreiben.
Viele Grüße
Hier ist eine weitere Möglichkeit, es mit mkstemp
der Python zu tun:
### 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