我有一个API,它包含可通过GET / POST / SOAP调用的ASP.NET webservices。
新功能需要我通过此Web服务接受文件。基本上我允许用户通过API将文件上传到文件存档,否则他们会登录我们基于浏览器的管理系统。
API需要尽可能容易地消费。我正在考虑放弃SOAP支持,因为我们的PHP客户端主要使用GET / POST方法,而.NET客户端并不介意。以此作为先决条件,我只想创建一个UploadFile(fileName)方法,并要求用户通过POST发送文件作为普通文件上传。
但是,我无法将文件字段指定为方法的参数,对吧?因此,如果我只是在文档中声明“文件应该在POST文件中发送,名为'文件'”,那么当我需要读取文件时会出现任何问题吗?
所有文件均采用二进制格式,PDF格式,各种图像格式,FLV等。此外,文件大小将主要在2-20MB附近,但鉴于上述解决方案,我是否有任何麻烦接受250MB区域的文件?
以这种方式接收文件会导致文件被完全加载到内存中,然后再将其写入磁盘 - 除了让服务接收Stream并因此禁止我接受其他参数之外,还有什么办法解决这个问题,以及阻碍了服务的简单使用?
除了我可能做的事情之外,我也很好奇我是如何让被调用者尽可能容易地发送文件的。我猜POST是接收文件最容易接受的方式之一,但如果有人有任何评论,我也想听听。
答案 0 :(得分:2)
“当我需要读取文件时,会不会出现任何问题?”没问题。处理POST请求时,您有POST的MIME附件,即文件。阅读此文件相对简单。
“接受250MB区域的文件会有什么麻烦吗?”不会。除了传输大文件需要一些时间。
“以这种方式接收文件会导致文件被完全加载到内存中”不一定是真的。许多Web服务器将请求处理到MIME附件并停止读取,使HTTP标头,请求和打开的套接字可用于进一步处理。我不知道ASP,但我知道几乎所有的框架都避免读取数据。该框架将其留给您的应用程序。
因此,您可以以块的形式读取数据并写入(或处理)这些块,而无需将整个内容读入内存。
POST正是这样做的。如果没有走出狭窄的HTTP Web服务空间,就没有很多选择。当然,您可以使用其他协议(如FTP(TFTP,SFTP))来移动文件,但这对于编写客户端应用程序的人来说常常令人困惑。
如果需要,您可以提供一个客户端库,该库使用POST方法创建HttpWebRequest
对象,并提供带附件的流。但是你不会节省太多,因为HttpWebRequest
类看起来很简单。这是一个code sample。
答案 1 :(得分:2)
使用简单的POST方法提交文件没有什么可怕的错误,只是将文件上传绑定到任何相关的元数据(即方法的其他参数,如果它与方法捆绑在一起)的细节。
今天,我认为在SOAP调用中处理大对象的方式是MTOM。这是一个优化,但它为您提供了实际有效负载的流接口。因此,框架可以在必要时将大对象缓存到磁盘(无论它们实际上是否是另一个问题,但没有人想要吸收250M上传到内存中,所以我想任何现代的都会卸载大型附件)
答案 2 :(得分:1)
但是,我无法将文件字段指定为方法的参数,对吧?因此,如果我只是在文档中声明“文件应该在POST文件中发送,名为'文件'”,那么当我需要读取文件时会出现任何问题吗?
没有理由不能包含额外的POST(或GET)参数。我可能会自己将文件名作为附加的POST参数,以便在请求中自动使用本地文件名的客户端可以轻松地重命名。如果我期望命名冲突,我甚至可以在发生冲突时返回服务器选择的名称...我认为REST人员使用某种HTTP Created状态代码。
所有文件均采用二进制格式,PDF格式,各种图像格式,FLV等。此外,文件大小将主要在2-20MB附近,但鉴于上述解决方案,我是否有任何麻烦接受250MB区域的文件?
您需要在web.config中调整maxRequestLengths和executionTimeouts。并且,如果有人尝试通过拨号上传250MB - 好吧,我们只是说它可能无法正常工作。
以这种方式接收文件会导致文件被完全加载到内存中,然后再将其写入磁盘 - 除了让服务接收Stream并因此禁止我接受其他参数之外,还有什么办法解决这个问题,以及阻碍了服务的简单使用?
ASP.NET 2.0+假脱机将文件上传到磁盘,以避免将整个请求预加载到RAM中。根据需要调整web.config的requestLengthDiskThreshold以平衡速度和内存使用情况。如果你想要的话,你就不能使用Stream ...尽管你可以接受byte []数组。我真的不确定那是什么意思......
对于小文件,你可以做base 64,这对客户来说应该是微不足道的。但是,对于20MB - 开销不值得。
有许多不同的ASP.NET文件上传组件 - 它们基本上作为HttpModule连接到Begin_Request,并拦截任何multippart / form-uploads的请求流。使用ASP.NET 2.0,这可能是不必要的,除非您想要提供某种进度回调或其他东西。如果是这种情况 - 它们的机制应该与Web服务一样。
RFC 1867是相关的规范,但如果您打算解析自己的请求,这个upload component可以很好地说明请求的内容。
我将拥有的一个问号是客户的http库中对multipart / form-data的支持程度。我怀疑它一切都很好,但你可能想检查一下。
答案 3 :(得分:0)
不是直接答案,但您可能还想查看BITS - Background Intelligent Transfer Service [wiki]
它可能与您/您的客户相关,也可能不相关。