Django / Python: ¿Cómo leer un archivo y validar que es un archivo de audio?

Posible duplicado:
Validación del archivo Django (audio)

Estoy creando una aplicación web, donde los usuarios pueden cargar contenido multimedia, incluidos archivos de audio.

Tengo un método limpio en mi AudioFileUploadForm que valida lo siguiente:

  • Que el archivo de audio no sea demasiado grande.
  • Que el archivo de audio tiene un tipo de contenido válido (tipo MIME).
  • Que el archivo de audio tenga una extensión válida.

Sin embargo, estoy preocupado por la seguridad . Un usuario puede cargar un archivo con código malicioso y pasar fácilmente las validaciones anteriores. Lo que quiero hacer a continuación es validar que el archivo de audio es, de hecho, un archivo de audio (antes de que se escriba en el disco).

¿Cómo debería hacer esto?

class UploadAudioForm(forms.ModelForm): audio_file = forms.FileField() def clean_audio_file(self): file = self.cleaned_data.get('audio_file',False): if file: if file._size > 12*1024*1024: raise ValidationError("Audio file too large ( > 12mb )") if not file.content_type in ['audio/mpeg','audio/mp4', 'audio/basic', 'audio/x-midi', 'audio/vorbis', 'audio/x-pn-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio', 'audio/vnd.rn-realaudio', 'audio/wav', 'audio/x-wav']: raise ValidationError("Sorry, we do not support that audio MIME type. Please try uploading an mp3 file, or other common audio type.") if not os.path.splitext(file.name)[1] in ['.mp3', '.au', '.midi', '.ogg', '.ra', '.ram', '.wav']: raise ValidationError("Sorry, your audio file doesn't have a proper extension.") # Next, I want to read the file and make sure it is # a valid audio file. How should I do this? Use a library? # Read a portion of the file? ...? if not ???.is_audio(file.content): raise ValidationError("Not a valid audio file.") return file else: raise ValidationError("Couldn't read uploaded file") 

EDITAR: Por “validar que el archivo de audio es, de hecho, un archivo de audio”, me refiero a lo siguiente:

Un archivo que contiene datos típicos de un archivo de audio. Me preocupa que un usuario pueda cargar archivos con encabezados apropiados y secuencias de comandos maliciosas en lugar de datos de audio. Por ejemplo … ¿es el archivo mp3 un archivo mp3? ¿O contiene algo no característico de un archivo mp3?

Una alternativa a la otra respuesta publicada que hace el análisis del header . Esto significa que alguien podría incluir otros datos detrás de un encabezado válido.

Es para verificar todo el archivo que cuesta más CPU pero también tiene una política más estricta. Una biblioteca que puede hacer esto es python audiotools y el método API relevante es AudioFile.verify .

Utilizado de esta manera:

 import audiotools f = audiotools.open(filename) try: result = f.verify() except audiotools.InvalidFile: # Invalid file. print("Invalid File") else: # Valid file. print("Valid File") 

Una advertencia es que este método de verify es bastante estricto y puede marcar los archivos mal codificados como no válidos. Debe decidir si este es un método adecuado o no para su caso de uso.

La idea es usar una utilidad como sndhdr para intentar leer un encabezado del archivo.

 from sndhdr import what import os from settings import MEDIA_ROOT ... if what( os.path.join( MEDIA_ROOT, file.name ) ) == None: # header parse failed, so, it could be a non-audio file. 

En este caso, debe asegurarse de que la utilidad no pueda reconocer un archivo que no sea de audio como un archivo de audio.

Nunca uso la utilidad sndhdr, por lo tanto, puede ser mejor usar otra. Por ejemplo también hay proyecto mutágeno .

Actualizar

El enfoque más profesional.

  1. Deje que un usuario cargue sus archivos sin la validación.
  2. Cree un campo de modelo especial asociado con un archivo: is_checked. Establece el campo Falso por defecto.
  3. No permita que otros usuarios descarguen los archivos que tienen is_checked == False
  4. Organice una tarea asíncrona que ejecute un software antimalware que verifique los archivos sin marcar. El software debe ser llamado como una función desde su tarea pythonic. La función debe responder a la pregunta: es un archivo en particular que tiene una parte de malware.
  5. Si el archivo actual tiene la parte de malware, elimínelo y elimine el registro del archivo. De lo contrario, configure is_checked = True desde su tarea.

¿Por qué una tarea separada? Porque la comprobación de este tipo de malware puede ser una operación larga.