2015-10-17 56 views
3

當某個請求遇到服務器(運行在移動應用上的服務器)時,我試圖將視頻文件作爲響應提供服務。例如:某人前往http://mylocalip:8080/video,我想用視頻爲他服務。如何向特定請求提供遠程文件(從遠程SMB服務器獲取)

這個視頻文件可以存儲在本地,也可以是外部的。我開始嘗試爲位於SMB服務器上的文件提供服務,因此我嘗試使用此代碼從服務器獲取文件並將其返回(我知道它正在等待整個文件讀取而不是讀取和發送塊,但應該可以工作對吧?):

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>") 
} 

但是,我不能讓它工作。我總是得到一個壞的管道錯誤,並且訪問Web服務器的網絡播放器(從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 
... 

使用從App內的本地播放器(KxMovie),這裏似乎被讀取文件頭,它得到正確的文件大小和視頻的尺寸。然而,它不會播放,它結束說它已經到達視頻的結尾(不播放它)。只是在這之後,Web服務器上顯示錯誤:

...  

[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文件。它也沒有工作。 最後,我嘗試提供包含在應用程序主包中的本地文件,並且發生了同樣的情況:什麼都沒有。下面是代碼:

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迴應...所以我敢肯定,我錯過有些東西,或者我安裝時錯過了一些框架ling WebServer(我不使用豆莢)? 在此先感謝

+0

您在SMB,視頻文件,手錶操作系統,網絡服務器之間的移動部件太多了......您應該先從Mac應用程序或iPhone應用程序提供常規本地文件,然後通過視頻文件提供,然後通過SMB最後移動到觀看操作系統。 – Pol

+0

您好波爾,感謝您的回覆。然而,在我的代碼中沒有任何與操作系統相關的問題!經過更多測試後,這裏的主要問題似乎與內容範圍有關,因爲我可以從受測試的所有文件(本地,smb,遠程等)谷歌Chrome桌面完美無瑕! 但是,當我嘗試iOS播放器或OS X Safari時,它會失敗......在開發者控制檯中告訴我有關'未能加載資源:插件模塊管理'的信息。 我知道如果他們存儲在本地,可以提供某種範圍文件......但第三方呢?我應該首先在本地下載它們嗎? – eiprol

+0

你應該更新這個問題的標題,因爲它太泛化,也不是真正的問題。 – Pol

回答

1

如果要使用視頻標記在瀏覽器中播放視頻文件(至少在Chrome和Safari上),則需要實施HTTP範圍請求。

如果您使用GCDWebServerFileResponse,GCDWebServer會自動執行範圍支持。如果您使用其他類型的響應,則需要根據傳入GCDWebServerRequestbyteRange屬性自行實施。您應該複製粘貼GCDWebServerFileResponse.m的邏輯。

+0

我想這個方法與此類似,然而,因爲我正在嘗試讀取外部/遠程文件(不存儲在與GCDWebServer相同的設備上),並將它們作爲對某些請求的響應,我不能在不改變它的情況下使用該類型(提供路徑,因爲GCDWebServerFileResponse提供服務存儲在SMB服務器上的文件將是無用的,我應該提供一種方法來讀取該文件異步(可能)並返回NSData。 也許我應該做一個混合GCDWebServerFileResponse(字節範圍),GCDWebServerStreamedResponse(異步讀取) – eiprol