Django 保存分块文件导致无效文件错误

Django save chunked files leading to invalid file errors

提问人:kipteam 提问时间:11/12/2023 最后编辑:kipteam 更新时间:11/14/2023 访问量:62

问:

在我的创建后端点中,我调用此函数来上传文件(目前出于调试目的,我立即运行assemble_attachment,但是当所有错误都得到修复时,它将作为自动化任务运行)

def _save_chunk(chunk: bytes, chunk_index, attachment_type: str, attachment_name: str, attachment_extension: str):
    if attachment_type == "VIDEO":
        destination = config.media_source + f'temporary/{attachment_name}_{chunk_index}.webm'

        with open(destination, 'wb') as file:
            file.write(chunk)

        return
    
    if attachment_type == "IMAGE":
        destination = config.media_source + f'temporary/{attachment_name}_{chunk_index}.webp'

        with open(destination, 'wb') as file:
            file.write(chunk)

        return
    
    if attachment_type == "AUDIO":
        destination = config.media_source + f'temporary/{attachment_name}_{chunk_index}.{attachment_extension}'

        with open(destination, 'wb') as file:
            file.write(chunk)

        return

def upload_attachment(attachment: UploadedFile, user_permissions: permissions.Permissions) -> tuple:
    # more code

    chunk_index = 1

    for chunk in attachment.chunks():
        _save_chunk(chunk, chunk_index, post_type, attachment_name, attachment_extension)

        chunk_index += 1

    print(f'Chunks saved in {time.time() - start_time} seconds.')

    post_attachment = models.PostAttachment.objects.create(
        attachment_type=post_type,
        name=attachment_name,
        extension=attachment_extension
    )

    assemble_attachments._assemble_attachment(post_attachment)

    # more code

在此示例中,我展示了保存图像的流程,但其他流程并非不稳定。 问题是有些文件会出错,而其他文件可以完美运行。

def _assemble_image(post_attachment: models.PostAttachment):
    destination = os.path.join(config.media_source, 'attachments', f'{post_attachment.name}.webp')

    image_chunks = []

    for file in os.listdir(config.media_source + 'temporary/'):
        if file.startswith(post_attachment.name):
            chunk_path = os.path.join(config.media_source, 'temporary', file)

            try:
                with open(chunk_path, 'rb') as chunk_file:
                    data = chunk_file.read()
                    if data:
                        image_chunks.append(data)
            except Exception as e:
                print(f"Error reading image chunk {chunk_path}: {e}")

            try:
                os.remove(chunk_path)
            except FileNotFoundError:
                pass

    try:
        if image_chunks:
            image = Image.open(io.BytesIO(b"".join(image_chunks)))

            if _is_animated(image):
                _process_frames(image, destination)
            else:
                image = ImageOps.exif_transpose(image)
                image.save(destination, format="WEBP", save_all=True)

            post_attachment.state = "assembled"
            post_attachment.save()

    except Exception as e:
        print(f"Error processing image chunks: {e}")

    return

def _assemble_attachment(post_attachment: models.PostAttachment):
    if post_attachment.attachment_type == "IMAGE":
        return _assemble_image(post_attachment)
        
    if post_attachment.attachment_type == "VIDEO":
        return _assemble_video(post_attachment)
    
    if post_attachment.attachment_type == "AUDIO":
        return _assemble_audio(post_attachment)

错误:

PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7f3e7e52e660>

我知道图像不是问题,因为我已将其保存在我的磁盘上,并且检查它没有问题。我还可以在应用程序的前端看到图像预览。为了进行测试,我还使用了一个图像处理函数,该函数没有分块,而是直接将图像加载到 PIL 中,该函数也完美运行。

def upload_attachment(attachment: UploadedFile, user_permissions: permissions.Permissions) -> tuple:
    # more code

    attachment_name = f"AT_{snowflakes.SnowflakeGenerator().generate_id}.webp"

    img = Image.open(attachment)

    if is_animated_image(img):
        # more code

    else:
        img = ImageOps.exif_transpose(img)

        img.save(f'{config.media_source}attachments/{attachment_name}', format='webp', save_all=True)

    # more code
python django python-imaging-库

评论


答: 暂无答案