2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩52頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、<p>  本科畢業(yè)設(shè)計(論文)</p><p><b> ?。ǘ?屆)</b></p><p>  基于Java的下載工具的設(shè)計與實現(xiàn)</p><p>  所在學(xué)院 </p><p>  專業(yè)班級 計算機科學(xué)與技術(shù) </p

2、><p>  學(xué)生姓名 學(xué)號 </p><p>  指導(dǎo)教師 職稱 </p><p>  完成日期 年 月 </p><p>  摘要:本設(shè)計采用Java設(shè)計一個具有斷點續(xù)傳和多線程下載功能的下載工具。整體使用Java

3、語言編寫,實現(xiàn)其基本功能,并在MyEclipse平臺上運行。能對指定的資源進(jìn)行下載,并解決資源下載中斷時,不能在原有的基礎(chǔ)上繼續(xù)下載,以及下載速度偏低等問題。本設(shè)計實現(xiàn)了基本GUI操作界面,操作簡單。但是下載文件路徑需要指定是個問題,需要改進(jìn)。當(dāng)然還有許多問題也待完善。</p><p>  關(guān)鍵字:Java;多線程;斷點續(xù)傳;Swing</p><p>  The Design and I

4、mplementation of Downloading tool based on Java</p><p>  Abstract: This design use Java to write which has the Multithread Download and Resume Broken Transfer functions. Use the Java language to achieve its

5、basic functions on the MyEclipse platform. It can download the appointed files, also give the solution to download interruption and download speed due to fast problems. This design achieved an easy GUI interface, simple

6、operation is required. But the download path must be specified is a problem, should be improved. Also many other problems may nee</p><p>  Keywords:Java; Multithreading; Swing; Resume broken transfer</p&

7、gt;<p><b>  目錄</b></p><p><b>  1. 引言1</b></p><p>  1.1 系統(tǒng)背景1</p><p>  1.2 系統(tǒng)意義1</p><p>  1.3 網(wǎng)絡(luò)構(gòu)架2</p><p><b>  2.

8、系統(tǒng)分析2</b></p><p>  2.1 設(shè)計概述2</p><p>  2.1.1 設(shè)計目標(biāo)2</p><p>  2.1.2 開發(fā)環(huán)境3</p><p>  2.2. 相關(guān)主要技術(shù)簡介3</p><p>  2.2.1 Java語言簡介3</p><p>  2

9、.2.2 多線程技術(shù)簡介3</p><p>  2.2.3 HTTP1.0協(xié)議4</p><p>  2.2.4 斷點續(xù)傳的技術(shù)4</p><p>  2.3 可行性分析5</p><p>  2.3.1 技術(shù)可行性分析5</p><p>  2.3.2 經(jīng)濟可行性分析6</p><p&

10、gt;  2.3.3 操作可行性分析7</p><p><b>  3. 概要設(shè)計8</b></p><p>  3.1 系統(tǒng)結(jié)構(gòu)圖9</p><p>  3.2 功能流程圖9</p><p>  4. 詳細(xì)設(shè)計10</p><p>  4.1 獲取網(wǎng)絡(luò)資源10</p>

11、<p>  4.1.1 功能說明11</p><p>  4.1.2 設(shè)計說明11</p><p>  4.1.3 核心代碼12</p><p>  4.2 線程任務(wù)分配12</p><p>  4.2.1 功能說明13</p><p>  4.2.2 設(shè)計說明13</p><

12、p>  4.2.3 設(shè)計流程13</p><p>  4.3 創(chuàng)建下載任務(wù)13</p><p>  4.4 任務(wù)下載13</p><p>  4.4.1 功能說明15</p><p>  4.4.2 設(shè)計說明15</p><p>  4.4.3 核心流程19</p><p> 

13、 4.5 事件監(jiān)聽器設(shè)計20</p><p>  4.5.1 功能說明20</p><p>  4.5.2 設(shè)計說明21</p><p>  4.6 下載控制器設(shè)計21</p><p>  4.6.1 功能說明22</p><p>  4.6.2 設(shè)計說明22</p><p>  4

14、.6.3 功能流程27</p><p>  4.7 顯示控制器設(shè)計26</p><p>  4.7.1 功能說明26</p><p>  4.7.2 設(shè)計說明26</p><p>  4.8 斷點記錄文件設(shè)計28</p><p>  4.8.1 功能說明27</p><p>  4.

15、8.2 設(shè)計說明27</p><p>  4.8.3 保存斷點線程流程圖28</p><p>  4.9 文件操作28</p><p>  4.9.1 功能說明28</p><p>  4.9.2 設(shè)計說明30</p><p>  4.9.3 文件操作流程30</p><p>  4

16、.10 GUI界面設(shè)計31</p><p>  4.10.1 功能說明31</p><p>  4.10.2 設(shè)計說明31</p><p>  5. 設(shè)計問題總結(jié)34</p><p>  5.1 斷點設(shè)置問題34</p><p>  5.2 下載速度統(tǒng)計問題34</p><p>&l

17、t;b>  致 謝36</b></p><p><b>  參考文獻(xiàn)資料36</b></p><p><b>  1. 引言</b></p><p><b>  1.1 系統(tǒng)背景</b></p><p>  隨著互聯(lián)網(wǎng)應(yīng)用范圍不斷發(fā)展,網(wǎng)絡(luò)包含的信息資源日

18、益增多,互聯(lián)網(wǎng)用戶可以通過網(wǎng)絡(luò)下載所需的數(shù)據(jù)資源保存在本地磁盤當(dāng)中,因此相應(yīng)的基于網(wǎng)絡(luò)的下載工具應(yīng)運而生。對于一個網(wǎng)絡(luò)下載工具,有兩個問題一直阻礙著下載技術(shù)的發(fā)展:速度和下載中斷問題。</p><p>  幾年來,下載技術(shù)也在不停地發(fā)展。最原始的下載功能僅僅是個“下載”過程,即從WEB服務(wù)器上連續(xù)地讀取文件。其最大的問題是,由于網(wǎng)絡(luò)的不穩(wěn)定性,一旦連接斷開使得下載過程中斷,就不得不全部從頭再來一次。隨后,“斷點續(xù)

19、傳”的概念就出來了,顧名思義,就是如果下載中斷,在重新建立連接后,跳過已經(jīng)下載的部分,而只下載還沒有下載的部分。</p><p>  在“網(wǎng)絡(luò)螞蟻”軟件流行開后,許多下載軟件也都紛紛效仿,是否具有“多線程下載”技術(shù)、甚至能支持多少個下載線程都成了人們評測下載軟件的要素?!岸嗑€程下載”的基礎(chǔ)是WEB服務(wù)器支持遠(yuǎn)程的隨機讀取,也即支持“斷點續(xù)傳”。這樣,在下載時可以把文件分成若干部分,每一部分創(chuàng)建一個下載線程進(jìn)行下載

20、。</p><p>  至于多線程下載的原理是這樣的:通常服務(wù)器同時與多個用戶連接,用戶之間共享帶寬。如果N個用戶的優(yōu)先級都相同,那么每個用戶連接到該服務(wù)器上的實際帶寬就是服務(wù)器帶寬的N分之一??梢韵胂?,如果用戶數(shù)目較多,則每個用戶只能占有可憐的一點帶寬,下載將會是個漫長的過程。但是伴隨著基于網(wǎng)絡(luò)的多線程下載技術(shù)的出現(xiàn),如今的下載工具徹底擺脫了這兩個問題的束縛并且向著更為人性化的方面發(fā)展下去。</p>

21、<p><b>  1.2 系統(tǒng)意義</b></p><p>  本系統(tǒng)是開發(fā)一個簡單的多線程下載工具,實現(xiàn)資源的多線程下載,同時實現(xiàn)斷點續(xù)傳的功能。實現(xiàn)這么一個下載最大的意義是探索多線程下載的基本原理,綜合運用大學(xué)四年所學(xué)的知識,提高自己的動手能力,及查閱資料繼續(xù)學(xué)習(xí)的能力,也是四年學(xué)習(xí)成果的展示,并完成學(xué)校的畢業(yè)設(shè)計任務(wù)。其次就是為用戶提供一個操作簡單、功能齊全的下載工具,

22、使用戶能更好的獲取網(wǎng)絡(luò)資源。</p><p>  多線程和傳統(tǒng)的單線程在程序設(shè)計上最大的區(qū)別在于,由于各個線程的控制流彼此獨立,使得各個線程之間的代碼亂序執(zhí)行,由此帶來的線程調(diào)度問題。由于是多線程進(jìn)行斷點續(xù)傳,還要考慮記錄多個斷點位置,且記錄斷點位置時也要考慮同步互斥等問題。所有這些都使得這一步比較復(fù)雜。但是可以明顯提高網(wǎng)絡(luò)文件的下載速度。</p><p><b>  1.3 網(wǎng)

23、絡(luò)構(gòu)架</b></p><p>  網(wǎng)絡(luò)下載基本構(gòu)架主要包括兩種:C/S與P2P架構(gòu)。傳統(tǒng)的C/S網(wǎng)絡(luò)發(fā)展出了HTTP/FTP下載,并在客戶端發(fā)展出了多線程下載方式。而P2P網(wǎng)絡(luò)則發(fā)展出了BT、eMule這樣的多源文件傳輸方式。</p><p>  傳統(tǒng)的HTTP/FTP下載方式都是屬于C/S架構(gòu),即客戶端/服務(wù)器架構(gòu)。這種模式的基本方法是將共享文件上傳服務(wù)器上,而需要這些文件

24、的用戶再向服務(wù)器索取和下載共享文件,也就意味著來自各個客戶端的大量的上傳下載數(shù)據(jù)都必須經(jīng)過服務(wù)器這個中轉(zhuǎn)站。</p><p>  BT協(xié)議則是屬于P2P架構(gòu),即PeertoPeer。雖然對于P2P并沒有一個統(tǒng)一的定義或標(biāo)準(zhǔn),但P2P都有一個共同點就是充分利用各結(jié)點的資源,形成一個自組織網(wǎng)絡(luò),在網(wǎng)絡(luò)中每個結(jié)點都是對等的,既享受別人的服務(wù)也為別人提供服務(wù),傳輸文件數(shù)據(jù)時不再需要經(jīng)過服務(wù)器。</p>&l

25、t;p><b>  2. 系統(tǒng)分析</b></p><p><b>  2.1 設(shè)計概述</b></p><p>  對于一個多線程下載工具的設(shè)計,首先就是要設(shè)定好實現(xiàn)的目標(biāo),確定開發(fā)的環(huán)境。只有明確了目標(biāo)才能知道自己要做什么,思路更清楚。而一個好的開發(fā)環(huán)境對提高開發(fā)的效率起著很重要的作用。</p><p>  2.

26、1.1 設(shè)計目標(biāo)</p><p>  實現(xiàn)一個實用的多任務(wù),多線程下載工具。具備以下功能:</p><p>  (1)實現(xiàn)一個簡潔的易操作的GUI界面。</p><p>  (2)實現(xiàn)新建下載任務(wù)的功能。</p><p>  (3)下載過程實現(xiàn)多任務(wù),多線程的功能。</p><p>  (4)實現(xiàn)任務(wù)暫停,及恢復(fù)下載的

27、功能。</p><p>  (5)實現(xiàn)停止任務(wù)功能。</p><p>  2.1.2 開發(fā)環(huán)境</p><p>  MyEclipse,Windows XP</p><p>  2.2. 相關(guān)主要技術(shù)簡介</p><p>  簡略的介紹下系統(tǒng)開發(fā)過程中用到的相關(guān)技術(shù)。如Java語言、多線程技術(shù)、HTTP1.0協(xié)議、斷點

28、續(xù)傳技術(shù)等。</p><p>  2.2.1 Java語言簡介</p><p>  Java是一種簡單、面向?qū)ο?、分布式、解釋型、健壯安全、結(jié)構(gòu)中立、可移植、性能優(yōu)異、多線程的語言,自1995年SUN推出JAVA語言后,全世界的目光都被這個神奇的語言所吸引。由于Java所具有的以上那些特性,并且在大學(xué)里也學(xué)習(xí)了兩個學(xué)期,對這門語言比較熟悉。所以選用JAVA作為本次畢業(yè)設(shè)計的開發(fā)語言。<

29、;/p><p>  2.2.2 多線程技術(shù)簡介</p><p>  線程是一組指令的集合,或者是程序的特殊段,它可以在程序里獨立執(zhí)行。也可以把它理解為代碼運行的上下文。所以線程基本上是輕量級的進(jìn)程,它負(fù)責(zé)在單個程序里執(zhí)行多任務(wù)。通常由操作系統(tǒng)負(fù)責(zé)多個線程的調(diào)度和執(zhí)行。利用線程,用戶可按下一個按鈕,然后程序會立即做出響應(yīng),而不是讓用戶等待程序完成當(dāng)前任務(wù)以后再做出響應(yīng)。</p>&

30、lt;p>  線程可以理解為下載的通道,一個線程就是一個文件的下載通道,多線程也就是同時開起好幾個下載通道.當(dāng)服務(wù)器提供下載服務(wù)時,使用下載者是共享帶寬的,在優(yōu)先級相同的情況下,總服務(wù)器會對總下載線程進(jìn)行平均分配。線程越多,下載速度越快。當(dāng)前的下載軟件都支持多線程技術(shù)。</p><p>  在本次設(shè)計中,多線程技術(shù)用在新建任務(wù)和下載過程上,在系統(tǒng)中可以開起多個下載線程下載同一網(wǎng)絡(luò)上的資源而互不干擾?;ゲ桓蓴_

31、也是相對的,首先下載的資源不能重復(fù),其次如何合理的分解整個資源,使得有相應(yīng)的線程對其進(jìn)行下載,下載結(jié)束后如何將資源重新整合等。線程的運行在操作系統(tǒng)的調(diào)度下,各自得到一定的時間片,當(dāng)某一線程獲取到時間片時,它就進(jìn)入運行狀態(tài)。各個線程按照一定的協(xié)議分別獲取時間片。</p><p>  當(dāng)對一個復(fù)雜對象進(jìn)行某種操作時,從操作開始到操作結(jié)束,被操作的對象往往會經(jīng)歷若干非法的中間狀態(tài)。調(diào)用一個函數(shù)(假設(shè)該函數(shù)是正確的)操作

32、某對象常常會使該對象暫時陷入不可用的狀態(tài)(通常稱為不穩(wěn)定狀態(tài)),等到操作完全結(jié)束,該對象才會重新回到完全可用的狀態(tài)。如果其他線程企圖訪問一個處于不可用狀態(tài)的對象,該對象將不能正確響應(yīng)從而產(chǎn)生無法預(yù)料的結(jié)果,如何避免這種情況發(fā)生是線程安全性的核心問題。</p><p>  線程同步提供了保證不同線程按適當(dāng)順序使用共享資源的工具。線程可直接訪問共享數(shù)據(jù),既有相互之間高效通信的優(yōu)點,也有線程間任意相互干擾的弊端。安全的

33、多線程數(shù)據(jù)使用方案要求不同線程處理不同的數(shù)據(jù),即多個線程不能共享臨界區(qū)。例如:有10張車票供2個顧客預(yù)定,而又要求2個顧客盡可能多地預(yù)定10張車票,這10張車票作為共享資源,可能導(dǎo)致1張票預(yù)定給2個顧客的情況,針對這種情況,設(shè)計時應(yīng)采用正確的同步機制。</p><p>  若2個線程同步執(zhí)行時需要相互打開,就會出現(xiàn)1個線程依賴于另1個要打開的線程而形成死鎖。它不是資源不夠引起的,而是由線程的調(diào)度引起的。對于死鎖可

34、用下述方法解決:</p><p>  (1)嘗試在盡可能短的時間內(nèi)執(zhí)行鎖定的代碼,占用時間越長,另一線程出現(xiàn)和需要對象的可能性越大。</p><p> ?。?)當(dāng)我們從另一個被同步的方法中激活被同步的方法時要小心,最好是清楚地定義每個線程的任務(wù),并考慮使用什么數(shù)據(jù)和什么時候使用。</p><p>  總之,在多線程程序設(shè)計中,要充分考慮各種可能出現(xiàn)的情況,并用適當(dāng)?shù)?/p>

35、方法給予解決,使線程在運行過程中按所預(yù)期定義的目標(biāo)進(jìn)行。</p><p>  2.2.3 HTTP1.0協(xié)議</p><p>  HTTP是Web協(xié)議集中的重要協(xié)議,它是從客戶機/服務(wù)器模型發(fā)展起來的??蛻魴C/服務(wù)器是運行一對相互通信的程序,客戶與服務(wù)器連接時,首先,向服務(wù)器提出請求,服務(wù)器根據(jù)客戶的請求,完成處理并給出響應(yīng)。瀏覽器就是與Web服務(wù)器產(chǎn)生連接的客戶端程序,它的端口為TCP的

36、80端口。舉一個大家都很常見的例子,瀏覽器與Web服務(wù)器之間所遵循的協(xié)議就是HTTP。</p><p>  Web的應(yīng)用層協(xié)議HTTP是Web的核心。HTTP在Web的客戶程序和服務(wù)器程序中得以實現(xiàn)。運行在不同端系統(tǒng)上的客戶程序和服務(wù)器程序通過交換HTTP消息交流。HTTP定義這些消息的結(jié)構(gòu)以及客戶和服務(wù)器如何交換這些消息。HTTP定義Web客戶(即瀏覽器)如何從Web服務(wù)器請求Web頁面,以及服務(wù)器如何把Web

37、頁面?zhèn)魉徒o客戶。</p><p>  HTTP1.0(Hypertext Transfer Protocol Vertion 1.0)超文本傳輸協(xié)議1.0。</p><p>  超文本傳輸協(xié)議(HTTP)是一種應(yīng)用層協(xié)議與速度分布必要的協(xié)作超媒體信息系統(tǒng)。這是一種一般、無狀態(tài)的、面向?qū)ο蟮膮f(xié)議,可用于多種任務(wù),例如域名服務(wù)器和分布式對象管理系統(tǒng),通過它的請求方法(命令)的延伸。一種特征HT

38、TP是代表性的數(shù)據(jù)輸入,使系統(tǒng)的獨立于數(shù)據(jù)生成轉(zhuǎn)移HTTP。它是用來在Internet上傳送超文本的傳送協(xié)議。它是運行在TCP/IP協(xié)議族之上的HTTP應(yīng)用協(xié)議,它可以使瀏覽器更加高效,使網(wǎng)絡(luò)傳輸減少。任何服務(wù)器除了包括HTML文件以外,還有一個HTTP駐留程序,用于響應(yīng)用戶請求。您的瀏覽器是HTTP客戶,向服務(wù)器發(fā)送請求,當(dāng)瀏覽器中輸入了一個開始文件或點擊了一個超級鏈接時,瀏覽器就向服務(wù)器發(fā)送了HTTP請求,此請求被送往由IP地址指定

39、的URL。駐留程序接收到請求,在進(jìn)行必要的操作后回送所要求的文件。[1]</p><p>  2.2.4 斷點續(xù)傳的技術(shù)</p><p>  在當(dāng)今的網(wǎng)絡(luò)時代,下載軟件是使用最為頻繁的軟件之一。幾年來,下載技術(shù)也在不停地發(fā)展。最原始的下載功能僅僅是個“下載過程”,即從WEB服務(wù)器上連續(xù)地讀取文件。其最大的問題是,由于網(wǎng)絡(luò)的不穩(wěn)定性,一旦連接斷開使得下載過程中斷,就不得不全部從頭再來一次。隨

40、后,“斷點續(xù)傳”的概念就出來了,顧名思義,就是如果下載中斷,在重新建立連接后,跳過已經(jīng)下載的部分,而只下載還沒有下載的部分。多線程下載的基礎(chǔ)是WEB服務(wù)器支持遠(yuǎn)程的隨機讀取,也即支持“斷點續(xù)傳”。這樣,在下載時可以把文件分成若干部分,每一部分創(chuàng)建一個下載線程進(jìn)行下載。這項技術(shù)在關(guān)機或者網(wǎng)絡(luò)出錯的情況下不僅能完整的保護你已下載的部分,還能使你重新連接下載時繼續(xù)下載未完成的部分。</p><p>  2.3 可行性分

41、析 </p><p>  可行性分析是通過對項目的主要內(nèi)容和配套條件進(jìn)行調(diào)查研究和分析比較,并對項目建成以后可能取得的經(jīng)濟效益及社會環(huán)境影響進(jìn)行預(yù)測,從而提出該項目是否值得投資和如何進(jìn)行建設(shè)的咨詢意見,為項目決策提供依據(jù)的一種綜合性的系統(tǒng)分析方法。可行性研究應(yīng)具有預(yù)見性、公正性、可靠性、科學(xué)性的特點??尚行匝芯繉嵸|(zhì)上是要進(jìn)行一次大大壓縮簡化了的系統(tǒng)分析和設(shè)計的過程,也就是在較高層次上以較抽象的方式進(jìn)行的系統(tǒng)分析和

42、設(shè)計的過程。它的目的不是解決問題,而是確定問題是否值得去解決。</p><p>  2.3.1 技術(shù)可行性分析</p><p>  多線程跨平臺的下載工具的實現(xiàn)不是很困難,首先是多線程,JAVA語言很好的支持了多線程,其API中的ExecutorService提供了多線程的處理。其次是跨平臺,JAVA語言本身就是平臺無關(guān)性的語言,編譯成class的字節(jié)碼文件,不同的平臺提供不同的JVM,確

43、保了JAVA的跨平臺性。第三是對協(xié)議的支持,API中的Java.net.*中提供了對HTTP支持的方法。最后也是最復(fù)雜的就是Java的圖形化界面,JAVA本身不擅長圖形化界面,但AWT及Swing也提供了足夠的支持。[2]</p><p>  首先要了解要做個什么樣的下載工具,對設(shè)計的技術(shù)實現(xiàn)全面的了解??梢圆捎胘ava的多線程機制,通過設(shè)置HTTP1.0的請求頭信息,可以實現(xiàn)連接遠(yuǎn)程資源,通過這個連接可以與遠(yuǎn)程

44、資源進(jìn)行交互,這樣就可以實現(xiàn)多線程及斷點續(xù)傳的功能。所以在技術(shù)上實現(xiàn)多線程下載是沒有問題。</p><p>  2.3.2 經(jīng)濟可行性分析</p><p>  贏利不是制作這個下載工具的目的,而只是為了探索多線程下載的基本原理,綜合運用所學(xué)的知識,提高自己的動手能力,及查閱資料繼續(xù)學(xué)習(xí)的能力,并完成學(xué)校安排的畢業(yè)設(shè)計,順利完成學(xué)業(yè)。所以它也就不存在經(jīng)濟的問題。而從它的意義上來說,絕對值得制

45、作這個下載工具。</p><p>  2.3.3 操作可行性分析</p><p>  下載工具應(yīng)面向廣大的互聯(lián)網(wǎng)用戶,所以在設(shè)計中采用簡潔的GUI界面。也因為簡潔的界面設(shè)計使得系統(tǒng)在操作方式上很容易讓用戶接受。即使對一個沒有計算機操作經(jīng)驗的人來</p><p>  說也能順利完成下載,因此在操作上也是行得通的。</p><p><b&g

46、t;  3. 概要設(shè)計</b></p><p><b>  3.1 系統(tǒng)結(jié)構(gòu)圖</b></p><p>  本系統(tǒng)采用三層結(jié)構(gòu)進(jìn)行系統(tǒng)分層,這三層分別為GUI表現(xiàn)層,控制層,底層下載操作,文件及網(wǎng)絡(luò)操作,系統(tǒng)的結(jié)構(gòu)圖如圖3-1</p><p>  圖3-1 系統(tǒng)結(jié)構(gòu)圖</p><p><b>  3

47、.2 功能流程圖</b></p><p>  新建下載及恢復(fù)下載功能流程圖見圖3-2,新建任務(wù)與恢復(fù)任務(wù)僅是在任務(wù)的構(gòu)建方式上不一樣,在網(wǎng)絡(luò)操作及下載操作上都沒有什么區(qū)別,這樣的實現(xiàn)主要得益于對代碼重用性的設(shè)計。</p><p>  圖3-2 新建/恢復(fù)任務(wù)流程圖</p><p>  暫停與停止的功能實現(xiàn)流程圖見圖3-3,從這個圖中可以發(fā)現(xiàn)和暫停任務(wù),停

48、止任務(wù)一樣具備同樣的代碼利用,停止線程過程是同一個,他們兩個在功能上唯一的不同僅是暫停任務(wù)時需要將暫停的斷點記錄下來,而停止任務(wù)卻是將斷點記錄給刪除,并刪除已下載的部分文件信息。</p><p>  圖3-3暫停/停止任務(wù)流程圖</p><p><b>  4. 詳細(xì)設(shè)計</b></p><p>  4.1 獲取網(wǎng)絡(luò)資源</p>

49、<p>  獲取網(wǎng)絡(luò)資源是下載過程中的第一個步驟,也是很關(guān)鍵的一步。由于網(wǎng)絡(luò)的問題是多變的,有可能指定的下載資源已經(jīng)不存在,或者網(wǎng)絡(luò)連接有問題,等一系列的問題,因此在連接資源過程中得對相應(yīng)的連接進(jìn)行測試,如輸入的URL是否正確或存在、網(wǎng)絡(luò)連接是否正常等。</p><p>  4.1.1 功能說明</p><p>  要下載一個遠(yuǎn)程的資源就需要先定位到指定的資源,并建立連接。在本模

50、塊中實現(xiàn)的基本功能說是與遠(yuǎn)程的資源進(jìn)行連接,并測試其連接狀態(tài)。</p><p>  4.1.2 設(shè)計說明</p><p>  在做這個模塊之前得先來了解下HTTP協(xié)議。HTTP協(xié)議就是超文本傳輸協(xié)議,采用了請求/響應(yīng)模型??蛻舳讼蚍?wù)器發(fā)送一個請求,請求頭包含請求的方法、URL、協(xié)議版本、以及包含請求修飾符、客戶信息和內(nèi)容的類似于MIME的消息結(jié)構(gòu)。服務(wù)器以一個狀態(tài)行作為響應(yīng),相應(yīng)的內(nèi)容包

51、括消息協(xié)議的版本,成功或者錯誤編碼加上包含服務(wù)器信息,實體元信息以及可能的實體內(nèi)容。</p><p><b>  1、連接資源</b></p><p>  通過JDK的net包中包含的URL及HttpURLConnection兩個類對網(wǎng)上資源進(jìn)行操作。URL指定網(wǎng)絡(luò)資源的位置,而HttpURLConnection中則封裝了操作指定網(wǎng)絡(luò)資源的方法。</p>

52、<p>  在本系統(tǒng)中設(shè)計了類SplitFileTask,它的主要功能就是通過提供指定的URL獲取HttpURLConnection對象,為控制層代碼利用HttpURLConnection對象操作網(wǎng)絡(luò)文件提供支持??刂茖哟a只要調(diào)用SplitFileTask.connection()即可。</p><p><b>  2、測試連接</b></p><p>

53、  在網(wǎng)絡(luò)連接過程中可能出現(xiàn)各種各樣的問題,而需要的只是連接成功的正確網(wǎng)絡(luò)資源,所以有必要對通過SplitFileTask獲取的與服務(wù)器的連接進(jìn)行測試。如果測試成功,即能正確獲取到指定的資源,之后才對指定的資源進(jìn)行下載操作,否則拋棄信息,并對用戶進(jìn)行相應(yīng)的提示。</p><p>  通過對HTTP1.0協(xié)議的了解,知道只要發(fā)送一個指定的請求頭信息,服務(wù)器就會返回一個攜帶著請求后服務(wù)器處理完成的信息,這個信息就包括

54、請求是否成功等。要做的就是構(gòu)造這樣一個帶有指定的請求的頭信息發(fā)送到服務(wù)器端,然后查看它返回的響應(yīng)碼,因為完成可能從響應(yīng)碼中去了解一個請求是否成功。</p><p>  要設(shè)計一個什么樣的請求頭才能符合的要求的測試效果呢?</p><p>  通過設(shè)計請求頭信息中的RANGE字段可以指定請求URL指向目標(biāo)資源的偏移量,而不是從頭開始讀。這個也是斷點及多線程下載資源的一個重要屬性,將在后面作更

55、詳細(xì)說明。如果設(shè)置完這個頭信息并發(fā)送到服務(wù)器端,如果源請求的資源存在并且服務(wù)器支持?jǐn)帱c續(xù)傳,這時它返回的響應(yīng)碼信息就是206,如果存在但不支持?jǐn)帱c則返回200,而其它的情況就都是連接失敗的情況了。[3]</p><p>  這樣測試連接的理論基礎(chǔ)就完成了,那用net包的類怎么設(shè)置請求頭信息,如何獲取響應(yīng)碼信息呢?其實這些都是很容易的,代碼如下:</p><p>  connection.s

56、etRequestProperty("Range","bytes="+downloaded+"-");設(shè)置請求頭的</p><p><b>  RANGE字段</b></p><p>  connection.getResponseCode();獲取響應(yīng)碼信息。到此,有關(guān)網(wǎng)絡(luò)連接,及測試連接的設(shè)計就告一段落了

57、。</p><p>  4.1.3 核心代碼</p><p><b>  (1)獲取連接</b></p><p>  如果獲取網(wǎng)絡(luò)資源出錯時則返回一個空值</p><p>  HttpURLConnection connection=(HttpURLConnection) url.openConniection();&l

58、t;/p><p>  connection.setRequestProperty("Range","bytes="+downloaded+"-");</p><p><b>  //連接服務(wù)器</b></p><p>  connection.connect();</p>&

59、lt;p><b>  //檢查返回值</b></p><p>  if(connection.getResponseCode()/100!=2){</p><p><b>  error();</b></p><p><b>  }</b></p><p>  //檢查文

60、件是不是有錯</p><p>  int contentLength=connection.getContentLength();</p><p>  if(contentLength<1){</p><p><b>  error();</b></p><p><b>  }</b><

61、/p><p><b>  (2)測試連接</b></p><p>  private URL verifyUrl(String url) {</p><p>  if(!url.toLowerCase().startsWith("http://"))</p><p>  return null;</

62、p><p>  URL verifiedUrl=null;</p><p><b>  try{</b></p><p>  verifiedUrl = new URL(url);</p><p>  }catch(Exception e){</p><p>  return null;</p&

63、gt;<p><b>  }</b></p><p>  if(verifiedUrl.getFile().length()<2)</p><p>  return null;</p><p>  return verifiedUrl;</p><p><b>  }[4]</b>

64、;</p><p>  4.2 線程任務(wù)分配</p><p>  通過對http1.0協(xié)議的了解后,知道通過對它的請求頭進(jìn)行設(shè)置,就可以獲取到遠(yuǎn)程文件的指定部分,而不用從頭開始下載。利用這個特性就可以設(shè)計一個多線程下載的原型出來了。要進(jìn)行多線程下載,主要實現(xiàn)的是為每個線程分配一個指定范圍的數(shù)據(jù)下載,那怎么為每一個下載線程進(jìn)行任務(wù)分配呢?這就是這一節(jié)要討論的內(nèi)容。</p>&l

65、t;p>  4.2.1 功能說明</p><p>  在多線程下載過程中,需要讓每一個線程都指向指定資源的一部分,且不重復(fù),如何為每一個下載線程分配它指向的特定部分就是這個模塊所要完成的任務(wù)。</p><p>  4.2.2 設(shè)計說明</p><p>  確定了采用分塊的形式進(jìn)行任務(wù)的分配,那要考慮的問題就只有如何分塊了,如何分配才能準(zhǔn)備無誤,并且保證各個下載

66、線程所要下載的任務(wù)更合理。本系統(tǒng)采用的是平均分配的方法。就是為每一個下載線程分配盡可能相同的字節(jié)數(shù),在這個過程中得指定下載任務(wù)相對于資源起點的偏移量及下載的長度。分配過程如下:</p><p>  獲取資源長度,這個可以從請求的響應(yīng)信息中獲取“filelength”字段獲得,即通過tempFile對象寫入文件信息獲取[5]。根據(jù)線程數(shù)計算各個任務(wù)塊的偏移量及下載長度,這個過程簡單,但得注意字節(jié)重復(fù)的問題。<

67、/p><p>  4.2.3 設(shè)計流程</p><p>  圖4-1 任務(wù)分配流程圖</p><p>  4.3 創(chuàng)建下載任務(wù)</p><p>  有了之前的一系列操作,就可以著手創(chuàng)建下載任務(wù)了,下載任務(wù)有很多不同的狀態(tài)和狀態(tài)信息,這些信息包括URL地址、文件保存路徑、下載文件長度、任務(wù)狀態(tài)、支持?jǐn)帱c標(biāo)志、下載進(jìn)度、下載狀態(tài)。并在程序里面設(shè)計一個

68、類FileInfo描述文件信息,詳細(xì)請看圖。FileInfo包括重寫了的hashCode()方法、以取得下載文件的信息進(jìn)行比較,equals()方法來驗證是否為續(xù)傳文件,通過傳入對象的下載文件URL和文件名區(qū)分是否為同一文件。[6]</p><p>  下圖是FileInfo圖4-2的類圖:</p><p>  圖4-2文件信息類圖</p><p>  創(chuàng)建下載任務(wù)

69、流程圖:</p><p>  圖4-3 創(chuàng)建下載任務(wù)流程</p><p><b>  4.4 任務(wù)下載</b></p><p>  任務(wù)下載模塊是本系統(tǒng)的核心,在任務(wù)運行過程中主要的時間也是在花這一塊,它的設(shè)計質(zhì)量,會對軟件的效率,占用資源的大小,軟件的可靠性及可用性有很大的影響。就拿軟件的可用性來說,因為在系統(tǒng)的下載過程中,讀取出來的長度是隨

70、機的,而且還要關(guān)心著本線程的下載范圍,因此如果未對其中的各個細(xì)節(jié)進(jìn)行考慮,很容易就會出現(xiàn)讀臟數(shù)據(jù)的情況,導(dǎo)致最終下載過來的數(shù)據(jù)無法使用。</p><p>  4.4.1 功能說明</p><p>  創(chuàng)建完任務(wù)就可以開始進(jìn)行下載操作了。在這個模塊中,要使用線程技術(shù)實現(xiàn)一個可重用的,較高效的實現(xiàn)程序。主要功能就是能讀取出指定資源相應(yīng)偏移量的數(shù)據(jù),并調(diào)用文件操作模塊將下載的數(shù)據(jù)保存到相應(yīng)文件中

71、去。</p><p>  4.4.2 設(shè)計說明</p><p>  SpliteFileTask類圖:</p><p>  圖4-4-2 分任務(wù)類圖</p><p><b>  核心代碼:</b></p><p><b>  // 執(zhí)行分任務(wù)</b></p>&

72、lt;p>  public void run()</p><p><b>  {</b></p><p>  if (isOver)// 如果分任務(wù)下載已完成,則退出</p><p><b>  {</b></p><p>  isStop = true;</p><p&g

73、t;<b>  return;</b></p><p><b>  }</b></p><p>  InputStream input = connection();</p><p>  byte[] b = new byte[10240];</p><p><b>  int len;&

74、lt;/b></p><p><b>  try</b></p><p><b>  {</b></p><p>  dataFile = new RandomAccessFile(saveFileName, "rw");</p><p>  while ((len = i

75、nput.read(b, 0, b.length)) > 0 && !isOver && !isStop)</p><p><b>  {</b></p><p>  dataFile.seek(startPos);// 定位輸入點</p><p>  dataFile.write(b, 0, len);&

76、lt;/p><p>  startPos += len;</p><p>  if (startPos >= endPos)</p><p><b>  {</b></p><p>  isOver = true;</p><p>  isStop = true;</p><

77、p><b>  }</b></p><p><b>  }</b></p><p>  } catch (IOException e)</p><p><b>  {</b></p><p>  e.printStackTrace();</p><p&

78、gt;<b>  }</b></p><p><b>  }</b></p><p><b>  // 連接資源</b></p><p>  private InputStream connection()</p><p><b>  {</b></

79、p><p><b>  try</b></p><p><b>  {</b></p><p>  URL url = new URL(siteURL);</p><p>  HttpURLConnection httpConnection = (HttpURLConnection) url</p

80、><p>  .openConnection();</p><p>  httpConnection.setRequestProperty("User-Agent", "NetFox");</p><p>  String bytes = "bytes=" + startPos + "-";

81、</p><p>  httpConnection.setRequestProperty("RANGE", bytes);</p><p>  InputStream input = httpConnection.getInputStream();</p><p>  return input;</p><p>  } c

82、atch (MalformedURLException e)</p><p><b>  {</b></p><p>  e.printStackTrace();</p><p>  } catch (IOException e)</p><p><b>  {</b></p><

83、;p>  e.printStackTrace();</p><p><b>  }</b></p><p>  return null;</p><p><b>  }</b></p><p>  本設(shè)計中采用了線程池技術(shù)ExecutorService。</p><p>

84、;  public interface ExecutorServiceextends ExecutorExecutor提供了管理終止的方法,以及可為跟蹤一個或多個異步任務(wù)執(zhí)行狀況而生成Future的方法。 </p><p>  可以關(guān)閉 ExecutorService,這將導(dǎo)致其拒絕新任務(wù)。提供兩個方法來關(guān)閉 ExecutorService.shutdown()方法在終止前允許執(zhí)行以前提交的任務(wù),而shutdow

85、nNow()方法阻止等待任務(wù)啟動并試圖停止當(dāng)前正在執(zhí)行的任務(wù)。在終止時,執(zhí)行程序沒有任務(wù)在執(zhí)行,也沒有任務(wù)在等待執(zhí)行,并且無法提交新任務(wù)。應(yīng)該關(guān)閉未使用的ExecutorService以允許回收其資源。</p><p>  通過創(chuàng)建并返回一個可用于取消執(zhí)行和/或等待完成的Future,方法submit擴展了基本方法Executor.execute(java.lang.Runnable)。方法invokeAny和i

86、nvokeAll是批量執(zhí)行的最常用形式,它們執(zhí)行任務(wù)collection,然后等待至少一個,或全部任務(wù)完成(可使用ExecutorCompletionService類來編寫這些方法的自定義變體)。</p><p>  Executors類提供了用于此包中所提供的執(zhí)行程序服務(wù)的工廠方法。</p><p>  下面給出了一個網(wǎng)絡(luò)服務(wù)的簡單結(jié)構(gòu),這里線程池中的線程作為傳入的請求。它使用了預(yù)先配置

87、的Executors.newFixedThreadPool(int)工廠方法: </p><p>  class NetworkService implements Runnable{</p><p>  private final ServerSocket serverSocket;</p><p>  private final ExecutorService

88、pool;</p><p>  public NetworkService(int port, int poolSize)</p><p>  throws IOException {</p><p>  serverSocket = new ServerSocket(port);</p><p>  pool = Executors.new

89、FixedThreadPool(poolSize);</p><p><b>  }[10]</b></p><p>  public void run() {</p><p><b>  try {</b></p><p>  for (;;) {</p><p>  po

90、ol.execute(new Handler(serverSocket.accept()));</p><p><b>  }</b></p><p>  } catch (IOException ex) {</p><p>  pool.shutdown();</p><p><b>  }</b>

91、;</p><p><b>  }</b></p><p><b>  }</b></p><p>  class Handler implements Runnable {</p><p>  private final Socket socket;</p><p>  H

92、andler(Socket socket) { this.socket = socket; }</p><p>  public void run() {</p><p><b>  }</b></p><p><b>  }</b></p><p>  下列方法分兩個階段關(guān)閉ExecutorSer

93、vice。第一階段調(diào)用shutdown拒絕傳入任務(wù),然后調(diào)用shutdownNow(如有必要)取消所有遺留的任務(wù):</p><p>  void shutdownAndAwaitTermination(ExecutorService pool) {</p><p>  pool.shutdown();</p><p><b>  try {</b&g

94、t;</p><p>  if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {</p><p>  pool.shutdownNow(); // Cancel currently executing tasks</p><p>  if (!pool.awaitTermination(60, TimeUnit.SEC

95、ONDS))</p><p>  System.err.println("Pool did not terminate");</p><p><b>  }</b></p><p>  } catch (InterruptedException ie) {</p><p>  pool.shutdow

96、nNow();</p><p>  Thread.currentThread().interrupt();</p><p><b>  }</b></p><p><b>  }</b></p><p>  內(nèi)存一致性效果:線程中向ExecutorService提交Runnable或Callable

97、任務(wù)之前的操作happen-before由該任務(wù)所提取的所有操作,后者依次happen-before通過Future.get()獲取的結(jié)果。[10]</p><p>  4.4.3 核心流程</p><p>  (1)子線程下載流程</p><p>  圖4-4 子線程下載流程圖</p><p><b>  (2)核心代碼</

98、b></p><p>  while((readBytes=is.read(buffer))!=-1&&!stop){</p><p>  size+=readBytes;//記錄已下載的字節(jié)數(shù)(未進(jìn)行無效數(shù)據(jù)刪減的)</p><p>  if(size>downFileLength){</p><p>  rea

99、dBytes=(int)(buffer.length-(size-downFileLength));</p><p>  flag=true;//設(shè)置下載范圍完成標(biāo)志</p><p>  //如果下載的長度大于要下載的長度減去多出來的部分,因為當(dāng)前線程只要求下載固定長度的文件</p><p><b>  }</b></p><

100、;p>  subThread.setDownedFileLength(subThread.getDownedFileLength()+readBytes);</p><p>  fo.saveFile(savePosition,buffer,saveFilePath,readBytes);</p><p>  //保存緩存的數(shù)據(jù)到文件中去</p><p>  

101、savePosition += readBytes;//設(shè)置保存偏移量</p><p>  task.setDownFileLength(task.getDownFileLength()+readBytes);</p><p>  //設(shè)置當(dāng)前任務(wù)的下載長度,用于下載進(jìn)度和速度統(tǒng)計</p><p><b>  if(flag){</b><

102、/p><p><b>  break;</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  if(!stop){</p><p>  subThread.setComplete(task,true);/

103、/設(shè)置線程下載完成,觸發(fā)下載完成事件</p><p><b>  }[7]</b></p><p>  4.5 事件監(jiān)聽器設(shè)計</p><p>  事件機制在這個設(shè)計中非常的重要,所有關(guān)于線程下載完成,任務(wù)下載完成的時候都是通過事件被觸發(fā)的方式完成。這種機制的好處就是不用開啟新的線程去監(jiān)視下載的情況,實時性上要比采用監(jiān)視線程要好很多,在消耗的資

104、源上也比開監(jiān)視線程要小很多,僅在事件被觸發(fā)時才進(jìn)行相應(yīng)的操作。</p><p>  4.5.1 功能說明</p><p>  在任務(wù)下載過程中,要進(jìn)行一系列的操作如:下載文件的保存,根據(jù)下載線程的完成情況判斷文件是否下載完畢等,所以本系統(tǒng)中設(shè)計了一個監(jiān)聽器用來監(jiān)聽事件的變化。[8]在初始化任務(wù)和下載線程時為它們注冊監(jiān)聽器,并在事件處理代碼中對相應(yīng)的事件進(jìn)行響應(yīng)。事件處理機制在本設(shè)計中占有很

105、大的比重。</p><p>  4.5.2 設(shè)計說明</p><p>  圖4-5 事件監(jiān)聽類圖</p><p>  通過方法重載給主界面MainFrame和給新建任務(wù)界面NewTask添加監(jiān)聽器:addToComponent()。</p><p>  此外監(jiān)聽類還實現(xiàn)了對下載的控制即暫停任務(wù),停止任務(wù),恢復(fù)任務(wù)同,移除已完成任務(wù)等操作。&l

106、t;/p><p>  取消任務(wù), 刪除table中的任務(wù):deleteTask()。</p><p>  關(guān)閉窗口的操作:exit()。</p><p>  讀取任務(wù)文件中的所有任務(wù) 并進(jìn)行初始化操作: init()。</p><p>  從第 row 行開始 刷新任務(wù)欄:initTable()。</p><p>  暫停

107、任務(wù):pause()。</p><p>  readTasks()和writeTasks()則分別從文件中讀取和保存文件信息。</p><p>  4.6 下載控制器設(shè)計</p><p>  本設(shè)計基本上符合MVC的設(shè)計模式,而作為C的部分,也是系統(tǒng)的核心部分。[9]系統(tǒng)中所有的命令都是通過下載控制器進(jìn)行轉(zhuǎn)發(fā),而GUI界面也就是通過下載控制器與網(wǎng)絡(luò),本地文件之間進(jìn)行

108、操作,從而實現(xiàn)系統(tǒng)的一個個功能。</p><p>  4.6.1 功能說明</p><p>  下載控制器在本設(shè)計中處于核心的地位,所有來自GUI界面的請求,還有底層網(wǎng)絡(luò)操作及文件的操作都通過控制器進(jìn)行協(xié)調(diào)工作??刂破髟谡麄€系統(tǒng)的運行周期中都存在著作用,在應(yīng)用程序剛剛啟動時,它需要讀取系統(tǒng)配置及上一次下載的斷點信息。所有對于下載的操作都要通過它來轉(zhuǎn)發(fā),甚至每一次斷點的保存都是通過它完成。&

109、lt;/p><p>  4.6.2 設(shè)計說明</p><p>  控制器實現(xiàn)了Runnable[10]和Serializable接口,使得控制器類具備父類處理下載事件的能力。</p><p><b>  類圖4-6:</b></p><p>  圖4-6 控制器設(shè)計類圖</p><p><b&g

110、t;  成員變量說明:</b></p><p>  fileinfo:用來保存當(dāng)前統(tǒng)中維護著的所有下載任務(wù)的信息,新建任務(wù)時就往當(dāng)中加入一個新的任務(wù)信息(NewTask),暫停任務(wù),停止任務(wù),恢復(fù)任務(wù)同,移除已完成等操作都要從fileinfo獲取信息或者寫入信息。</p><p>  fileLength:獲得文件的長度</p><p>  startP

111、os:分任務(wù)開始位置</p><p>  endPos:分任務(wù)結(jié)束位置</p><p>  countThread:分任務(wù)的數(shù)目</p><p>  isFirst:是否第一次取文件</p><p>  isStop: 停止標(biāo)志</p><p>  tempFile:文件下載的臨時信息</p><p

112、>  executor:線程池</p><p>  private JTable viewTable = null;</p><p><b>  row:任務(wù)編號</b></p><p>  speed:任務(wù)下載的速度[11]</p><p><b>  核心代碼:</b></p>

113、<p>  public void run()</p><p><b>  {</b></p><p>  if (fileInfo.isOver())// 入文件已下載完畢,則結(jié)束任務(wù)返回</p><p><b>  return;</b></p><p><b>  el

114、se</b></p><p>  isStop = false;// 否則,將isStop 置為false</p><p>  tempFile = new File(fileInfo.getFilePath() + File.separator</p><p>  + fileInfo.getFileName() + ".info"

115、);</p><p>  countThread = fileInfo.getConutThread();// 分任務(wù)的數(shù)目</p><p>  if (tempFile.exists())</p><p>  {// 文件已存在,是續(xù)傳文件</p><p>  isFirst = false;</p><p>  S

116、ystem.out.println("文件已存在,是續(xù)傳文件" + tempFile);</p><p>  readFilePos();// 讀取保存的下載信息(文件指針位置)</p><p><b>  } else</b></p><p><b>  {</b></p><p&

117、gt;  startPos = new long[countThread];</p><p>  endPos = new long[countThread];</p><p>  splitTask = new SplitFileTask[countThread];</p><p>  fileLength = getFileLong();// 獲取文件的長度&l

118、t;/p><p>  if (fileLength <= 0)</p><p><b>  {</b></p><p>  JOptionPane jp = new JOptionPane("網(wǎng)絡(luò)資源不正確!");</p><p>  jp.createDialog("提示信息"

119、);</p><p><b>  return;</b></p><p><b>  }</b></p><p>  fileInfo.setStartDate(Calendar.getInstance());// 設(shè)置任務(wù)開始時間</p><p>  fileInfo.setFileLength(

120、fileLength);// 設(shè)置文件的長度</p><p><b>  }</b></p><p>  long tem = fileLength / countThread;// 每個分任務(wù)的長度</p><p>  if (isFirst)</p><p><b>  {// 若是第一次</b>

121、;</p><p>  for (int i = 0; i < countThread; i++)</p><p><b>  {</b></p><p>  startPos[i] = i * tem; // 分任務(wù)開始位置</p><p><b>  }</b></p>&l

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論