Web services 在web服务器中动态创建流文件存档
我有一个允许上传文件的应用程序(但问题比这个更一般)。我还允许文件加载。我想让用户下载单链接多个文件。根据这个问题:唯一的解决方案似乎是创建包含所有文件的文件归档 我想在Haskell的恒定内存中使用Hackage提供的库来完成,而不需要写入磁盘或执行外部程序 尤其是以下非解决方案:Web services 在web服务器中动态创建流文件存档,web-services,haskell,compression,yesod,Web Services,Haskell,Compression,Yesod,我有一个允许上传文件的应用程序(但问题比这个更一般)。我还允许文件加载。我想让用户下载单链接多个文件。根据这个问题:唯一的解决方案似乎是创建包含所有文件的文件归档 我想在Haskell的恒定内存中使用Hackage提供的库来完成,而不需要写入磁盘或执行外部程序 尤其是以下非解决方案: 调用外部程序来创建存档:文件可能位于磁盘上或某个数据库中,可以通过某个远程url访问。文件系统可能是“只读”的。出于安全原因,可能无法执行外部程序。外部程序使部署复杂化 从源文件在磁盘上创建临时存档:请参阅上面的
- 调用外部程序来创建存档:文件可能位于磁盘上或某个数据库中,可以通过某个远程url访问。文件系统可能是“只读”的。出于安全原因,可能无法执行外部程序。外部程序使部署复杂化
- 从源文件在磁盘上创建临时存档:请参阅上面的“只读”文件系统。效率也很低:写入磁盘实际上相当慢
- 在内存中创建完整的归档文件并随后提供:这些文件可能相当大(比如CD图像)并且有多个。需要的内存太大了
Archive
类型的值。例如,它可能如下所示:
import Codec.Archive.Zip
-- ... and in your code:
let archiveTemplate =
Archive
{ zComment = ByteString.pack "Downloaded from mysite.com"
, zSignature = Nothing
, zEntries = []
}
let filesIWantToInclude = ["foo.png", "bar.iso"]
entries <- forM filesIWantToInclude $ readEntry []
let archive = foldr addEntryToArchive archiveTemplate entries
let byteString = fromArchive archive
-- Now you can send the byteString over the network, or something.
import Codec.Archive.Zip
-- ... 在您的代码中:
让拱形模板=
档案文件
{zComment=ByteString.pack“从mysite.com下载”
,zSignature=无
,zEntries=[]
}
让filesIWantToInclude=[“foo.png”、“bar.iso”]
条目如果您在内存中执行此操作,并且有10个用户每人下载5 x 100MB的文件,则仅存档就需要5GB+的RAM。似乎没有特别的可扩展性。@如果你读了这个问题,@Tener明确地不想将整个存档保存在内存中。有很多gzip
和zip
的实现可以动态压缩内容并流式传输。@dflemstr哎呀,错过了问题的最后一部分。尽管如此,即使在中等负载的情况下,这似乎也会摧毁服务器的CPU;在某些情况下,要比SSL加密快得多。你知道吗?它速度如此之快,几乎总是值得去做的。我确实看过这个图书馆。乍一看,这似乎不是一个解决办法。我没有测试它,但从源代码看,readEntry使用toEntry,它试图变得聪明,并且只在需要时进行压缩。测试是通过压缩整个文件并查看是否有帮助来完成的。我认为这将使整个文件存储在内存中,因此整个库将消耗太多内存。不过,手动创建条目是可能的。不过我需要crc32计算的代码。你可以复制内部压缩方法,省去大小比较。。。