2010-09-13 14 views
28

Estoy intentando capturar un archivo enviado con el formulario y realizar algunas operaciones antes de que se guarde. Entonces necesito crear una copia de este archivo en el directorio temporal, pero no sé cómo llegar a él. Las funciones de Shutil no pueden copiar este archivo, ya que no hay una ruta hacia él. Entonces, ¿hay alguna manera de hacer esta operación de otra manera?Cómo copiar el objeto InMemoryUploadedFile al disco

Mi código:

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) 

Lo que plantea:

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

Y la depuración:

# (..)\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' 

Respuesta

39

This es pregunta similar, podría ayudar.

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) 
+0

Hii, creo que codificado el "tmp/name.mp3" será un problema en la ruta de plataforma cruzada, trato de mejorar su código

 from django.conf import settings tmp = os.path.join(settings.MEDIA_ROOT, "tmp", data.name) path = default_storage.save(tmp, ContentFile(data.read()))

+2

No me gusta aquí ** data.read() ** –

+0

@ sube lo que está mal con data.read() ?? –

5

Su mejor curso de acción es escribir un controlador personalizado Cargar. Ver el docs. Si agrega un controlador "file_complete", puede acceder al contenido del archivo independientemente de tener un archivo de memoria o un archivo de ruta temporal. También puede usar el método "receive_data_chunck" y escribir su copia dentro de él.

Saludos

+0

Estaba usando esto por un tiempo hasta cuando se carga un nombre duplicado y django agrega automáticamente un sufijo para hacer que el nombre del archivo sea único. Ese nombre de archivo renombrado no estaba disponible en el nivel del controlador de carga. Aparte de eso, esto funcionó muy limpiamente. – awwester

1

Aquí hay otra manera de hacerlo con el pitón de 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 
7

Como se ha mencionado por @ups, al cargar archivos de gran tamaño, que no quiere obstruir la memoria del sistema con un data.read().

De 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) 

Esto guardará el archivo en MEDIA_ROOT/tmp/ como su default_storage voluntad a menos que se lo indique.

+0

Me gusta esto: FileNotFoundError: [Errno 2] No existe dicho archivo o directorio: '// .png'. Ideas? – Daviddd

+0

@Daviddd el archivo no está donde usted cree que es, y es irrelevante para este código. –

Cuestiones relacionadas