2013-12-19 43 views
0

在我的服務器程序中,我應該從客戶端取一個文件,但這可以是任意大小,所以我怎麼才能知道它的大小,以便我可以爲它設置緩衝區大小。我試過這個代碼,但最後我只是得到1kb文件夾,這是不工作了。尋找傳入文件的大小

   private void checkRequest() 
     { // Checks if request is a download or upload request and calls function that fits. 
... 
... 
... 
      else if (Request.Contains("Upload")) //If request is upload (Client wants to upload) 
     { 
      info = Request; 
      nickName = Request.Substring(0, Request.IndexOf("Upload")); //Takes nickname 
      info = info.Replace(nickName, ""); //Takes nickName of the client and deletes 
      info = info.Replace("Upload", ""); //Deletes request. 

      if (!sList.Contains(nickName)) //If nick name is unique 
      { 
       info = info.Substring(0, info.IndexOf("end")); 

       sList.Add(nickName); //Adds nick name into a list. 
       Receive(info); 
      } 
     } 
     else 
     { 
      serverSocket.Close(); // If any problem occurs server becomes offline. 
     } 
    } 
    private void Receive(string receivedFileName) 
    { 
     byte[] buffer = new byte[1024]; //This is the part I can't fit anything. 
     activity.AppendText("File downloading to " + fileDir + " destination"); 
     while (tempSocket.Receive(buffer) != 0) 
     { 
      File.WriteAllBytes(fileDir + "//" + fileName, buffer); //Creates a new file or overwrites it. 

     } 
     activity.AppendText("File downloaded..."); // Updates activity log(text box.) 

    } 
+0

'tempSocket.Receive(緩衝)'不garunteed經常閱讀'buffer.Length'字節,你需要檢查從'Receive'的結果,只使用很多'buffer'中的字節。同樣來自[WriteAllBytes]上的MSDN(http://msdn.microsoft.com/en-us/library/system.io.file.writeallbytes%28v=vs.110%29.aspx)「*創建一個新文件,將指定的字節數組寫入文件,然後關閉該文件。**如果目標文件已經存在,它將被覆蓋**。*「,您需要使用附加內容而不是覆蓋文件。 –

回答

1

你做File.WriteAllBytes()函數調用之前,寫了Int64拿出來與文件長度的插座。

然後讓您的客戶先查找該長度,並適當設置緩衝區。

備註

如果你想在TCP流僅從文件中包含的數據,你可以有一個包含多個套接字協議:

  • 控制插座 - 這個插座就會等待連接告訴它一個文件需要上傳。一旦客戶端連接,客戶端將傳遞它的信息,如file size。然後服務器將用新端口的端口進行響應。 (數據插座
  • 數據套接字 - 當客戶端連接到此套接字時,它會立即發送整個文件。一旦服務器收到約定的字節數,它將關閉套接字。
+0

在數據之前發送大小是個不好的做法,因爲它打破了流設計。流不知道什麼時候它會結束,直到它結束... –

+0

@WouterHuysentruit如果你沒有辦法告訴文件何時完成傳輸,除非另一端在最後關閉流,或者檢查一個代表流結束的特殊模式(但在發送之前,您必須確保該文件不包含該模式)。如果你打開這個流,你可以發送一個任意大小的文件。正如你所說的,數據流不知道它什麼時候結束直到它結束,所以你必須添加元數據來告訴接收器多少期望。 –

+0

哦錯過了這個流保持打開的事實。 –

0

由於您將套接字打開,所以您確實必須首先按照Andrew的建議發送文件的大小。

但即使如此,也不要將所有內容讀入內存中的數組,而是考慮使用FileStream並將數據直接寫入磁盤中。

喜歡的東西:

private void Receive(string receivedFileName) 
{ 
    byte[] buffer = new byte[1024]; 
    // receive file size 
    if (tempSocket.Receive(buffer, sizeof(ulong), SocketFlags.None) != sizeof(ulong)) 
    { 
     // failed to receive the size 
     return; 
    } 
    ulong fileSize = BitConverter.ToUInt64(buffer, 0); 
    // receive file data 
    activity.AppendText("File downloading to " + fileDir + " destination"); 
    using (FileStream stream = new FileStream(fileDir + "//" + fileName, FileMode.Create, FileAccess.Write) 
    { 
     ulong totalBytesReceived = 0; 
     while (totalBytesReceived < fileSize) 
     { 
      int bytesReceived = tempSocket.Receive(buffer); 
      if (bytesReceived > 0) 
      { 
       stream.Write(buffer, 0, bytesReceived); 
       totalBytesReceived += (ulong)bytesReceived; 
      } 
      else 
      { 
       Thread.Sleep(1); 
      } 
     } 
    } 
    activity.AppendText("File downloaded..."); // Updates activity log(text box.) 
}