You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PyScript加载Zip文件并保存至虚拟文件系统

PyScript加载本地Zip文件失败问题排查与解决

问题背景

尝试用PyScript加载本地Zip文件到虚拟文件系统,目标是打开Zip并列出其中内容。目前已实现:

  • 成功加载PyScript,支持文件选择操作
  • 能创建虚拟Zip文件并保存到虚拟文件系统,可正常列出其内容
  • 虚拟Zip文件能被process_file函数正确处理

但选择本地有效Zip文件时,始终无法正常解析,触发格式错误。

错误信息

选择本地Zip文件后,出现以下核心错误:

File "/lib/python3.10/zipfile.py", line 1353, in _RealGetContents
    raise BadZipFile("Bad magic number for central directory")
zipfile.BadZipFile: Bad magic number for central directory

尝试用ArrayBuffer/Stream等方式读取时,还会出现类型错误:

TypeError: a bytes-like object is required, not 'pyodide.JsProxy'

问题根源

核心错误在于用文本方式读取二进制Zip文件:原代码中await f.text()将二进制Zip文件按UTF-8文本读取,再通过bytes(data,'utf-8')转回字节流。这个过程会破坏二进制数据(Zip文件包含大量非UTF-8兼容的字节),导致Zip文件的魔术数字(用于识别Zip格式的标识字节)被篡改,无法被zipfile.ZipFile识别。

解决方案

改用二进制方式读取文件:利用File对象的arrayBuffer()方法获取原始二进制数据,再转换为Python的bytes对象,最后用BytesIO包装供zipfile处理。

修改process_file函数如下:

async def process_file(event):
    fileList = event.target.files.to_py()
    for f in fileList:
        # 读取原始二进制ArrayBuffer
        buffer = await f.arrayBuffer()
        # 将JS ArrayBuffer转换为Python可识别的bytes对象
        data = bytes(buffer)
        mf = io.BytesIO(data)

        with zipfile.ZipFile(mf, "r") as zf:
            nl = zf.namelist()
            nlf = " _ ".join(nl)
            document.getElementById("content").innerHTML = nlf

完整修改后的代码

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
    <title>Example</title>
</head>

<body>

    <p>Example</p>
    <br />
    <label for="myfile">Select a file:</label>
    <input type="file" id="myfile" name="myfile">
    <br />
    <br />
    <div id="print_output"></div>
    <br />
    <p>File Content:</p>
    <div style="border:2px inset #AAA;cursor:text;height:120px;overflow:auto;width:600px; resize:both">
        <div id="content">
        </div>
    </div>

    <py-script output="print_output">
        import asyncio
        import zipfile
        from js import document
        from pyodide import create_proxy
        import io

        async def process_file(event):
            fileList = event.target.files.to_py()
            for f in fileList:
                buffer = await f.arrayBuffer()
                data = bytes(buffer)
                mf = io.BytesIO(data)

                with zipfile.ZipFile(mf, "r") as zf:
                    nl = zf.namelist()
                    nlf = " _ ".join(nl)
                    document.getElementById("content").innerHTML = nlf

        def main():
            file_event = create_proxy(process_file)
            e = document.getElementById("myfile")
            e.addEventListener("change", file_event, False)

            mf = io.BytesIO()
            with zipfile.ZipFile(mf, mode="w",compression=zipfile.ZIP_DEFLATED) as zf:
                zf.writestr('file1.txt', b"hi")
                zf.writestr('file2.txt', str.encode("hi"))
                zf.writestr('file3.txt', str.encode("hi",'utf-8'))  
            with open("a.txt.zip", "wb") as f:
                f.write(mf.getvalue())
            
            with zipfile.ZipFile("a.txt.zip", "r") as zf:
                nl=zf.namelist()
                nlf=" ".join(nl)

            document.getElementById("content").innerHTML = nlf

        main()
    </py-script>

</body>

</html>

内容的提问来源于stack exchange,提问作者whydoesntwork

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:16:02