在保存文件之前,我想在字节级别上编辑一个上传的文件(即搜索和删除某个字节序列)。
我用以下方式设置了一个pre_save信号:
class Snippet(models.Model):
name = models.CharField(max_length=256, unique=True)
audio_file = models.FileField(upload_to=generate_file_name, blank=True, null=True)
@receiver(models.signals.pre_save, sender=Snippet)
def prepare_save(sender, instance, **kwargs):
if instance.audio_file:
remove_headers(instance)现在,我在实现remove_headers函数时遇到了问题,我可以在文件还在内存中时编辑它,然后再将它存储起来。除其他外,我尝试了以下几点:
def remove_headers(instance):
byte_sequence = b'bytestoremove'
f = instance.audio_file.read()
file_in_hex = f.hex()
file_in_hex = re.sub(byte_sequence.hex(), '', file_in_hex)
x = b''
x = x.fromhex(file_in_hex)
tmp_file = TemporaryFile()
tmp_file.write(x)
tmp_file.flush()
tmp_file.seek(0)
instance.audio_file.save(instance.audio_file.name, tmp_file, save=True)首先,这将导致一个无限循环。但是,这可以通过例如只在create上调用remove_headers方法来缓解。但是它没有工作,文件没有改变。我还尝试将最后一行替换为:
instance.audio_file = File(tmp_file, name=instance.audio_file.name)但是,这会导致一个空文件被写入/保存。奇怪的是,在编写测试时,这种方法似乎有效:
def test_header_removed(self):
snippet = mommy.make(Snippet)
snippet.audio_file.save('newname.mp3', ContentFile('contentbytestoremovecontent'))
snippet.save()
self.assertEqual(snippet.audio_file.read(), b'contentcontent')此测试不会失败,尽管文件最终为零字节。我在这里错过了什么?
发布于 2018-05-25 08:31:40
第二个解决方案几乎是正确的。文件最终为空(实际上只发生在较大的文件中)的原因是,有时您必须在打开文件后查找文件的开头。因此,需要更改remove_headers的初学者:
def remove_headers(instance):
byte_sequence = b'bytestoremove'
instance.audio_file.seek(0)
f = instance.audio_file.read()
file_in_hex = f.hex()https://stackoverflow.com/questions/50472164
复制相似问题