草庐IT

ios - 如何为某些请求提供远程文件(从远程 SMB 服务器获取)

coder 2023-09-11 原文

当某些请求到达服务器(在移动应用程序上运行的服务器)时,我正在尝试提供视频文件作为响应。例如:有人去 http://mylocalip:8080/video ,我想用视频服务他。

这个视频文件可以存储在本地,也可以是外部的。我开始尝试提供位于 SMB 服务器上的文件,所以我尝试使用此代码从服务器获取文件并将其返回(我知道它正在等待读取整个文件而不是读取和发送 block ,但应该可以工作对吧?):

webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
            print("########\n########Request: \(request)")
            let webrequested:GCDWebServerRequest = request;
            let urlcita:String = String(webrequested.URL)
            print("URL of requests\(urlcita)")
            if urlcita.rangeOfString("videosmb") != nil{
                print("It's a video SMB request")

                //Test fake SMB file predefined. Read File using KxSMB

                let route:String = "smb://192.168.1.205/ServidorAH/video.avi";
                let extensFile:NSString = (route as NSString).pathExtension
                let contentype = GCDWebServerGetMimeTypeForExtension(extensFile as String);
                print("Content type MIME \(contentype)")


                //Open SMB file using KxSMB
                let authcredentials = KxSMBAuth.smbAuthWorkgroup("", username: "Guest", password: "");
                let provider = KxSMBProvider.sharedSmbProvider()!
                let archivoes = provider.fetchAtPath(route, auth: authcredentials)

                //Switch to manually end the reading when switched to true. In the future will send chunks of data until the end, instead of reading the whole file first.
                var interruptor:Bool = false

                //Response Stream block
                let responseStream: GCDWebServerStreamedResponse = GCDWebServerStreamedResponse(contentType: contentype, asyncStreamBlock: { completionBlock in

                    if (interruptor == true)
                    {
                        print("Test: End of reading")
                        completionBlock(NSData(), nil);
                    }

                    if archivoes!.isKindOfClass(NSError){
                        //It can not find the file, SMB error, so empty NSDATA to completion block
                        let errorcito:NSError = archivoes as! NSError
                        print("Error obteniendo archivo SMB: \(errorcito.localizedDescription)");
                        completionBlock(NSData(), nil);
                    }else{
                        print("Archivo SMB adecuado \(archivoes)")
                        let datos:NSData = archivoes!.readDataToEndOfFile()
                        //Print lenght of data (to check the size of the file)
                        print("Data lenght \(datos.length)")
                        //Set switch to true, so the next call will send an empty daya completion block
                        interruptor = true
                        //Send data chunk (in this case everything)
                        completionBlock(datos, nil);
                    }

                })
                return responseStream


            }else{
                //Default response
                return GCDWebServerDataResponse(HTML:"<html><body><p>Hello World<br></p></body></html>")
 }

但是,我无法让它工作。我总是遇到管道损坏错误,并且访问网络服务器的网络播放器(也从 Mac 和 iOS 浏览)不播放任何内容。我还尝试使用嵌入式 iOS 播放器来记录响应 (KxMovie)。我得到这样的东西:

[DEBUG] Did open connection on socket 19
[DEBUG] Connection received 177 bytes on socket 19
[DEBUG] Connection on socket 19 preflighting request "GET /videosmb" with 177 bytes body
[DEBUG] Connection on socket 19 processing request "GET /videosmb" with 177 bytes body
[DEBUG] Did connect
[DEBUG] Did start background task
[DEBUG] Connection sent 175 bytes on socket 19
...

使用应用程序内部的本地播放器 (KxMovie),这里似乎是在读取文件 header ,并获得正确的文件大小和视频尺寸。但是它不播放并且结束时说它到达了视频的结尾(没有播放)。紧接着,WebServer 显示错误:

...       

[ERROR] Error while writing to socket 19: Broken pipe (32)
[DEBUG] Did close connection on socket 19
[VERBOSE] [fe80::cd0:28cd:3a37:b871%en1:8080] fe80::cd0:28cd:3a37:b871%en1:50109 200 "GET /videosmb" (177 | 175)
[DEBUG] Did disconnect
[DEBUG] Did end background task

考虑到这是我第一次与 SMB 服务器打交道,我想也许我在 SMB 部分做错了什么,所以我决定采用一种仅用于测试的简化方法。 这次我尝试提供一个存储在远程网络服务器(不是 SMB)上的简单 mp4 文件。它也没有用。 最后,我尝试提供包含在应用程序主 bundle 中的本地文件,同样的事情发生了:什么都没有。这是代码:

webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
       print("########\n########Request: \(request)")
       let webrequested:GCDWebServerRequest = request;
       let url:String = String(webrequested.URL)
       print("URL of request: \(url)")
       if url.rangeOfString("video") != nil{
            print("It's a video request")

            let rutalocalita = (NSBundle.mainBundle()).pathForResource("video", ofType: "avi")
            let datos = NSData(contentsOfFile: rutalocalita!)!
            print("video size: \(datos.length)")
            return GCDWebServerDataResponse(data: datos, contentType: "video/avi")

        }else{
           //Default Response: Simple web
           return GCDWebServerDataResponse(HTML:"<html><body><p>Hello World<br></p></body></html>")
        }
})

这是日志的样子:

[DEBUG] Did open connection on socket 19
[DEBUG] Connection received 177 bytes on socket 19
[DEBUG] Connection on socket 19 preflighting request "GET /video" with 177 bytes body
[DEBUG] Connection on socket 19 processing request "GET /video" with 177 bytes body
[DEBUG] Did connect
[DEBUG] Did start background task
[myCUSTOMDebug] Read 13584902 b. I'm going to send the response back to the request.
[DEBUG] Connection sent 173 bytes on socket 19
...

这里是我在应用程序内部使用的本地播放器来跟踪响应,能够读取如下内容:

header='HTTP/1.1 200 OK'
2015-10-17 17:51:41.571 videotvtest[262:14252] http_code=200
2015-10-17 17:51:41.571 videotvtest[262:14252] header='Cache-Control: no-cache'
2015-10-17 17:51:41.571 videotvtest[262:14252] header='Content-Length: 13584902'
2015-10-17 17:51:41.572 videotvtest[262:14252] header='Content-Type: video/avi'
2015-10-17 17:51:41.572 videotvtest[262:14252] header='Connection: Close'
2015-10-17 17:51:41.573 videotvtest[262:14252] header='Server: GCDWebServer'

...
[ERROR] Error while writing to socket 19: Broken pipe (32)
[DEBUG] Did close connection on socket 19
[VERBOSE] [fe80::cd0:28cd:3a37:b871%en1:8080] fe80::cd0:28cd:3a37:b871%en1:50155 200 "GET /video" (177 | 173)
netbios_ns_send_name_query, name query sent for '*'.
[DEBUG] Did disconnect
[DEBUG] Did end background task

为此我正在尝试使用 tvOS 和 Xcode 7,但我想如果我能够显示常规 HTML 响应应该没问题...所以我确定我遗漏了什么,或者也许我在安装 WebServer 时错过了一些框架(我没有使用 Pod)? 提前致谢

最佳答案

如果您想要使用视频标签提供可以在浏览器中播放的视频文件,至少在 Chrome 和 Safari 上,您需要实现 HTTP 范围请求。

如果您使用 GCDWebServerFileResponse,GCDWebServer 会自动实现范围支持。如果您使用其他类型的响应,则需要根据传入的 GCDWebServerRequestbyteRange 属性自行实现。您应该从 GCDWebServerFileResponse.m 复制粘贴逻辑。

关于ios - 如何为某些请求提供远程文件(从远程 SMB 服务器获取),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33188728/

有关ios - 如何为某些请求提供远程文件(从远程 SMB 服务器获取)的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  6. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  7. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  8. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  9. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  10. ruby - 如何为 emacs 安装 ruby​​-mode - 2

    我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby​​提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs

随机推荐