<p>你想做的事情是不可能的,正如<a href="https://stackoverflow.com/a/51604927/908494">John Rotenstein's answer</a>所解释的那样。您不必将zipfile下载到本地<em>存储</em>,但至少要下载到本地<em>内存</em>,耗尽您的本地带宽。无法在S3上运行任何代码。在</p>
<p>不过,不管怎样,还是有办法得到你真正想要的东西。在</p>
<p>如果你可以下载,比方说,8KB的文件,而不是整个5GB,这就足够了吗?如果是这样,如果你愿意做一点工作,那么你就幸运了。如果你不得不下载,比如说,1MB,但是可以做的工作少很多呢?在</p>
<hr/>
<p>如果1MB听起来不算太糟,而且你愿意接受一些黑客攻击:</p>
<p>您只需要统计zipfile中有多少个文件。对于zipfile,所有这些信息都可以在中心目录中找到,这是文件末尾的一小块数据。在</p>
<p>如果您拥有整个中心目录,即使丢失了文件的其余部分,stdlib中的<code>zipfile</code>模块也能很好地处理它。虽然<em>没有记录到</em>这样做,但是,至少在最近的CPython和pypy3.x中包含的版本中,它肯定会这样做。在</p>
<p>所以,你能做的是:</p>
<ul>
<li>发出一个<a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4" rel="nofollow noreferrer">^{<cd2>}</a>请求,只获取标题。(在<code>boto</code>中,使用<a href="https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.head_object" rel="nofollow noreferrer">^{<cd4>}</a>进行此操作。)</li>
<li>从<code>Content-Length</code>头提取文件大小。</li>
<li>用一个<code>GET</code>请求一个<a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35" rel="nofollow noreferrer">^{<cd7>}</a>头,只从<code>size-1048576</code>下载到最后。(在<code>boto</code>中,我相信您可能需要调用<a href="https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.get_object" rel="nofollow noreferrer">^{<cd10>}</a>,而不是<code>download*</code>便利方法之一,并且您必须自己格式化<code>Range</code>头值。)</li>
</ul>
<p>现在,假设您在缓冲区<code>buf</code>中有最后的1MB:</p>
<pre><code>z = zipfile.ZipFile(io.BytesIO(buf))
count = len(z.filelist)
</code></pre>
<p>通常,1MB就足够了。但如果不是呢?好吧,这就是事情变得有些棘手的地方。<code>zipfile</code>模块知道您还需要多少字节,但它提供给您这些信息的唯一位置是异常描述的文本。所以:</p>
^{pr2}$
<hr/>
<p>如果1MB听起来已经太多带宽了,或者您不想依赖<code>zipfile</code>模块的未记录行为,那么您只需要做更多的工作。在</p>
<p>在几乎每种情况下,您甚至不需要整个中心目录,只需要<code>total number of entries</code>字段,<code>end of central directory record</code>字段是位于中心目录末尾的更小的数据块。在</p>
<p>因此,请执行上述操作,但只读取最后8KB而不是最后1MB。在</p>
<p>然后,基于<a href="https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT" rel="nofollow noreferrer">zip format spec</a>,编写自己的解析器。在</p>
<p>当然,您不需要编写完整的解析器,甚至不需要接近它。您只需要处理从<code>total number of entries</code>到最后的字段。除<code>zip64 extensible data sector</code>和/或<code>.ZIP file comment</code>之外,所有这些字段都是固定大小的字段。在</p>
<p>偶尔(例如,对于有大量注释的zipfiles),您需要阅读更多的数据来获得计数。这应该是相当罕见的,但如果出于某种原因,它在你的zipfiles中更常见,你可以把8192的猜测改成更大的值。在</p>