欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

C#實現(xiàn)http斷點續(xù)傳上傳和下載的實現(xiàn)示例


2024年3月12日 21:55 本文熱度 650

斷點續(xù)傳是一種可以在文件傳輸過程中出現(xiàn)斷電、網(wǎng)絡(luò)故障等情況時,能夠保證傳輸內(nèi)容不會全部丟失,而是可以從已傳輸?shù)奈恢美^續(xù)傳輸?shù)臋C制。在文件傳輸較大、較復(fù)雜的情況下,使用斷點續(xù)傳可以提高傳輸質(zhì)量、穩(wěn)定性和效率。

在C#中,可以使用HTTP協(xié)議的Range頭部域來實現(xiàn)斷點續(xù)傳。使用HTTP Range頭部域,可以控制取哪個字節(jié)范圍內(nèi)的字節(jié)。具體實現(xiàn)方法,在HTTP請求頭中填寫Range頭部信息,指明下載區(qū)間:

Range: bytes=[start]-[end]

start和end的值為0和文件大小減1,表示下載全部數(shù)據(jù);若要實現(xiàn)斷點續(xù)傳,則start的值為當(dāng)前已下載的數(shù)據(jù)大小,end的值不變。

在本篇文章中,我們將詳細介紹如何使用C#實現(xiàn)HTTP協(xié)議的斷點續(xù)傳功能,并提供了完整的代碼示例。

實現(xiàn)步驟

C#實現(xiàn)斷點續(xù)傳功能的步驟,簡要描述如下:

1.定義HTTP請求,并填寫Range頭部信息,指明下載區(qū)間信息。

2.執(zhí)行HTTP請求,接收服務(wù)端返回的字節(jié)流,并將流寫入本地文件。

3.檢查最終下載文件的大小,與服務(wù)端的文件大小是否一致,若不一致則下載失敗。

4.上傳文件時,同樣需制定Range信息,然后發(fā)送PUT請求進行上傳。

代碼實現(xiàn)

我們將使用HttpClient來執(zhí)行請求,使用FileStream來讀寫文件。下面是代碼實現(xiàn)的詳細過程。

1.下載文件

下載文件時,首先需要判斷本地是否已經(jīng)存在相同的文件,如果存在,則需要計算出當(dāng)前已下載數(shù)據(jù)的大小(即起始位置startPosition),否則從頭開始下載。

下載時,需要在HTTP請求頭中填寫Range頭部信息,指明下載區(qū)間。同時,需要注意控制下載緩沖區(qū)大小,以避免內(nèi)存不足的情況。

最后,需要檢查下載完成后文件的大小是否與服務(wù)端的文件大小一致,若不一致,則下載失敗。

代碼示例:

1.  private static async Task DownloadFileAsync(Uri uri, string filename, CancellationToken cancellationToken = default)

2.  {

3.      long startPosition;

4.      var fileInfo = new FileInfo(filename);

5.   

6.      if (fileInfo.Exists)

7.      {

8.          startPosition = fileInfo.Length;

9.          if (startPosition == uri.GetFileSize())

10.        {

11.            Console.WriteLine($"The file '{filename}' has already been downloaded.");

12.            return;

13.        }

14.    }

15.    else

16.    {

17.        startPosition = 0;

18.    }

19.

20.    using var fs = new FileStream(filename, startPosition == 0 ? FileMode.Create : FileMode.Append);

21.

22.    var rangeHeader = new RangeHeaderValue(startPosition, null);

23.

24.    var request = new HttpRequestMessage(HttpMethod.Get, uri);

25.    request.Headers.Range = rangeHeader;

26.

27.    using var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);

28.    var contentLength = response.Content.Headers.ContentLength;

29.    if (!contentLength.HasValue)

30.    {

31.        throw new InvalidOperationException("The server did not provide the content length.");

32.    }

33.

34.    var totalSize = contentLength.Value + startPosition;

35.

36.    using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);

37.    await stream.CopyToAsync(fs);

38.

39.    if (fs.Length != totalSize)

40.    {

41.        fileInfo.Refresh();

42.        if (fileInfo.Length < totalSize)

43.        {

44.            throw new InvalidOperationException($"The file '{filename}' was not downloaded correctly.");

45.        }

46.    }

47.

48.    Console.WriteLine($"The file '{filename}' has been downloaded.");

49.}

2.上傳文件

上傳文件與下載文件相似,同樣需要在HTTP請求頭中填寫Range頭部信息,以限制上傳的范圍。同時,需要指定Content-Type,以明確上傳數(shù)據(jù)的類型。

上傳文件需要注意的一點是,如果文件較大,則需要分多次上傳。可以將文件分割成多個大小相同的片段,逐個上傳,確保操作的穩(wěn)定性和效率。

上傳完成后,會收到服務(wù)端的響應(yīng)。如果響應(yīng)碼為2xx,則表示上傳成功;否則,表示上傳失敗。

代碼示例:

1.  public static async Task UploadFileAsync(Uri uri, string filename, int bufferSize = 4096, CancellationToken cancellationToken = default)

2.  {

3.      long startPosition;

4.      var fileInfo = new FileInfo(filename);

5.   

6.      if (fileInfo.Exists)

7.      {

8.          startPosition = fileInfo.Length;

9.      }

10.    else

11.    {

12.        throw new FileNotFoundException("The file was not found.", filename);

13.    }

14.

15.    using var fs = new FileStream(filename, FileMode.Open);

16.

17.    var rangeHeader = new RangeHeaderValue(startPosition, fs.Length - 1);

18.

19.    var request = new HttpRequestMessage(HttpMethod.Put, uri);

20.    request.Headers.Range = rangeHeader;

21.    request.Headers.TryAddWithoutValidation("Content-Type", "application/octet-stream");

22.

23.    var content = new StreamContent(fs, bufferSize);

24.    request.Content = content;

25.

26.    using var response = await HttpClient.SendAsync(request, cancellationToken);

27.

28.    if (!response.IsSuccessStatusCode)

29.    {

30.        var responseMessage = await response.Content.ReadAsStringAsync();

31.        throw new InvalidOperationException($"Failed to upload file: {response.StatusCode} {responseMessage}");

32.    }

33.

34.    Console.WriteLine($"The file '{filename}' has been uploaded.");

35.}

完整代碼

上述代碼僅為示例,仍然需要加入部分邊界檢查、異常處理等邏輯,以保證代碼的健壯性。下面是完整的實現(xiàn)代碼,包含了斷點續(xù)傳功能的完整實現(xiàn)。

1.  using System;

2.  using System.IO;

3.  using System.Net.Http;

4.  using System.Net.Http.Headers;

5.  using System.Threading;

6.  using System.Threading.Tasks;

7.   

8.  namespace ConsoleApp

9.  {

10.    internal static class Program

11.    {

12.        private static readonly HttpClient HttpClient = new HttpClient();

13.

14.        private static async Task Main(string[] args)

15.        {

16.            var uri = new Uri("https://download.visualstudio.microsoft.com/download/pr/26246709-5c10-4383-ad1a-f22f3e8e5e15/23e2d41d2e57b81fc0f9c72068994e70/vc_redist.x64.exe");

17.

18.            var filename = Path.Combine(Path.GetTempPath(), "vc_redist.x64.exe");

19.

20.            Console.WriteLine("Start downloading the file...");

21.

22.            try

23.            {

24.                await DownloadFileAsync(uri, filename, CancellationToken.None);

25.            }

26.            catch (Exception ex)

27.            {

28.                Console.WriteLine($"Failed to download the file: {ex.Message}");

29.                return;

30.            }

31.

32.            Console.WriteLine("\nStart uploading the file...\n");

33.

34.            try

35.            {

36.                await UploadFileAsync(uri, filename, 4096, CancellationToken.None);

37.            }

38.            catch (Exception ex)

39.            {

40.                Console.WriteLine($"Failed to upload the file: {ex.Message}");

41.                return;

42.            }

43.

44.            Console.WriteLine("Done.");

45.        }

46.

47.        private static async Task DownloadFileAsync(Uri uri, string filename, CancellationToken cancellationToken = default)

48.        {

49.            long startPosition;

50.            var fileInfo = new FileInfo(filename);

51.

52.            if (fileInfo.Exists)

53.            {

54.                startPosition = fileInfo.Length;

55.                if (startPosition == uri.GetFileSize())

56.                {

57.                    Console.WriteLine($"The file '{filename}' has already been downloaded.");

58.                    return;

59.                }

60.            }

61.            else

62.            {

63.                startPosition = 0;

64.            }

65.

66.            using var fs = new FileStream(filename, startPosition == 0 ? FileMode.Create : FileMode.Append);

67.

68.            var rangeHeader = new RangeHeaderValue(startPosition, null);

69.

70.            var request = new HttpRequestMessage(HttpMethod.Get, uri);

71.            request.Headers.Range = rangeHeader;

72.

73.            using var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);

74.            var contentLength = response.Content.Headers.ContentLength;

75.            if (!contentLength.HasValue)

76.            {

77.                throw new InvalidOperationException("The server did not provide the content length.");

78.            }

79.

80.            var totalSize = contentLength.Value + startPosition;

81.

82.            using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);

83.            await stream.CopyToAsync(fs);

84.

85.            if (fs.Length != totalSize)

86.            {

87.                fileInfo.Refresh();

88.                if (fileInfo.Length < totalSize)

89.                {

90.                    throw new InvalidOperationException($"The file '{filename}' was not downloaded correctly.");

91.                }

92.            }

93.

94.            Console.WriteLine($"The file '{filename}' has been downloaded.");

95.        }

96.

97.        public static async Task UploadFileAsync(Uri uri, string filename, int bufferSize = 4096, CancellationToken cancellationToken = default)

98.        {

99.            long startPosition;

100.                   var fileInfo = new FileInfo(filename);

101.        

102.                   if (fileInfo.Exists)

103.                   {

104.                       startPosition = fileInfo.Length;

105.                   }

106.                   else

107.                   {

108.                       throw new FileNotFoundException("The file was not found.", filename);

109.                   }

110.        

111.                   using var fs = new FileStream(filename, FileMode.Open);

112.        

113.                   var rangeHeader = new RangeHeaderValue(startPosition, fs.Length - 1);

114.        

115.                   var request = new HttpRequestMessage(HttpMethod.Put, uri);

116.                   request.Headers.Range = rangeHeader;

117.                   request.Headers.TryAddWithoutValidation("Content-Type", "application/octet-stream");

118.        

119.                   var content = new StreamContent(fs, bufferSize);

120.                   request.Content = content;

121.        

122.                   using var response = await HttpClient.SendAsync(request, cancellationToken);

123.        

124.                   if (!response.IsSuccessStatusCode)

125.                   {

126.                       var responseMessage = await response.Content.ReadAsStringAsync();

127.                       throw new InvalidOperationException($"Failed to upload file: {response.StatusCode} {responseMessage}");

128.                   }

129.        

130.                   Console.WriteLine($"The file '{filename}' has been uploaded.");

131.               }

132.           }

133.        

134.           public static class UriExtensions

135.           {

136.               public static long GetFileSize(this Uri uri)

137.               {

138.                   using var client = new HttpClient();

139.                   using var response = client.Send(new HttpRequestMessage(HttpMethod.Head, uri));

140.                   var contentLength = response.Content.Headers.ContentLength;

141.                   if (!contentLength.HasValue)

142.                   {

143.                       throw new InvalidOperationException("The server did not provide the content length.");

144.                   }

145.        

146.                   return contentLength.Value;

147.               }

148.           }

149.       }

總結(jié)

斷點續(xù)傳功能可以在文件傳輸?shù)倪^程中,提高傳輸質(zhì)量和效率,確保數(shù)據(jù)傳輸?shù)陌踩院头€(wěn)定性。在本文中,我們介紹了C#中實現(xiàn)HTTP協(xié)議斷點續(xù)傳的方法,并提供了完整的代碼示例。希望讀者通過本文的介紹,能夠成功實現(xiàn)斷點續(xù)傳功能,并在實際工作中應(yīng)用到相應(yīng)的場景中去。


該文章在 2024/3/12 23:35:13 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved