Django: Cómo permitir una operación de archivo sospechoso / copiar un archivo

Quiero hacer un SuspiciousFileOperation que django no permite de forma predeterminada.

Estoy escribiendo un comando (para ejecutarlo a través de manage.py importfiles ) para importar una estructura de directorio dada en el sistema de archivos real en mi propio archivo de almacenamiento de archivos en Django.

Creo que este es mi código relevante:

 def _handle_directory(self, directory_path, directory): for root, subFolders, files in os.walk(directory_path): for filename in files: self.cnt_files += 1 new_file = File(directory=directory, filename=filename, file=os.path.join(root, filename), uploader=self.uploader) new_file.save() 

El retroceso es:

 Traceback (most recent call last): File ".\manage.py", line 10, in  execute_from_command_line(sys.argv) File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 399, in execute_from_command_line utility.execute() File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 392, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "C:\Python27\lib\site-packages\django\core\management\base.py", line 242, in run_from_argv self.execute(*args, **options.__dict__) File "C:\Python27\lib\site-packages\django\core\management\base.py", line 285, in execute output = self.handle(*args, **options) File "D:\Development\github\Palco\engine\filestorage\management\commands\importfiles.py", line 53, in handle self._handle_directory(args[0], root) File "D:\Development\github\Palco\engine\filestorage\management\commands\importfiles.py", line 63, in _handle_directory new_file.save() File "D:\Development\github\Palco\engine\filestorage\models.py", line 157, in save self.sha512 = hashlib.sha512(self.file.read()).hexdigest() File "C:\Python27\lib\site-packages\django\core\files\utils.py", line 16, in  read = property(lambda self: self.file.read) File "C:\Python27\lib\site-packages\django\db\models\fields\files.py", line 46, in _get_file self._file = self.storage.open(self.name, 'rb') File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 33, in open return self._open(name, mode) File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 160, in _open return File(open(self.path(name), mode)) File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 261, in path raise SuspiciousFileOperation("Attempted access to '%s' denied." % name) django.core.exceptions.SuspiciousFileOperation: Attempted access to 'D:\Temp\importme\readme.html' denied. 

El modelo completo se puede encontrar en GitHub . El comando completo está actualmente en gist.github.com disponible .

Si no desea comprobar el modelo: el file de atributos de mi clase de File es un FileField .

Supongo que este problema ocurre porque simplemente estoy “enlazando” al archivo encontrado. Pero necesito copiarlo, ¿eh? ¿Cómo puedo copiar el archivo en el archivo?

Analizando esta parte de stacktrace:

 File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 261, in path raise SuspiciousFileOperation("Attempted access to '%s' denied." % name) 

conduce a la Django FileSystemStorage estándar. Espera que los archivos estén dentro de tu MEDIA_ROOT . Sus archivos pueden estar en cualquier parte del sistema de archivos, por lo tanto, este problema ocurre.

Debe pasar un objeto similar a un archivo en lugar de una ruta a su modelo de File . La forma más fácil de lograrlo sería usar la clase de File Django, que es un envoltorio alrededor de los objetos tipo python. Consulte la documentación del objeto Archivo para obtener más detalles.

Actualizar:

Ok, estoy sugiriendo aquí una ruta tomada de los documentos:

 from django.core.files import File as FileWrapper ... path = os.path.join(root, filename) with open(path, 'r') as f: file_wrapper = FileWrapper(f) new_file = File(directory=directory, filename=filename, file=file_wrapper, uploader=self.uploader) new_file.save() 

Si funciona, debe copiar el archivo en la ubicación provista por su secure_storage .

En Django, SuspiciousFileOperation se puede evitar al leer el archivo desde un directorio externo y hacer un archivo tmp dentro del medio del proyecto y luego guardarlo en el archivo apropiado que se presenta a continuación.

 import tempfile file_name="file_name.pdf" EXT_FILE_PATH = "/home/somepath/" file_path = EXT_FILE_PATH + file_name if exists(file_path): #create a named temporary file within the project base , here in media lf = tempfile.NamedTemporaryFile(dir='media') f = open(file_path, 'rb') lf.write(f.read()) #doc object with file FileField. doc.file.save(file_name, File(lf), save=True) lf.close() 

Compruebe si hay una barra antes de su ruta de archivo

 file_item = models.FileField(upload_to=content_file_name) def content_file_name(username, filename): return '/'.join(['content', username, filename]) 

Note aquí "content" no "/content" . Ese fue el problema para mí.