1. 程式人生 > >stream外掛跨域大檔案斷點續傳實戰+自定義限速

stream外掛跨域大檔案斷點續傳實戰+自定義限速

JAVA跨域大檔案斷點續傳+自定義限速
前言:本文所講到的內容完全獨創,遇坑很多,但是本著資源共享的原則,將兩個星期的成果分享給大家,請尊重別人的勞動成果,轉載請註明出處:http://blog.csdn.net/qq_27063119,謝謝! 先講述一下本文所針對的問題: 1.跨域,所謂跨域就是就是伺服器之間的分離,如,一個系統中,應用程式為在一個伺服器上,而應用程式往往需要上傳檔案,將上傳檔案作為獨立的一個功能放在另外的一臺伺服器上,這時上傳檔案就是跨域了,若將上傳檔案部分也放在應用伺服器上,一旦流量過大,伺服器癱瘓,那麼會導致主應用程式也不能夠使用。 2.大檔案斷點續傳 , 這是基於HTML5標準,因此IE9(包括IE9)以下瀏覽器不支援,為了相容了IE6以上的瀏覽器上傳,只能選擇
使用flash進行上傳,但是此時不可以斷點續傳。 3.自定義限制檔案上傳的速度  ,對原始碼進行修改時的支援自定義限速功能。 (第一種)以下為簡單整合上傳的方法(不跨域可以使用):     這裡我們藉助了stream上傳外掛,這是官網:http://www.twinkling.cn  ,然後點選下載頁,通過開源中國或者百度雲盤下載官方的例項1.8.1.xxx,需要下載stream-1.8.1.10157.war,以及stream-1.8.0.10076-r.jar,官方的JAVA後臺程式碼jiangdx-stream-master.zip只有從開源中國上面下載,準備好這兩個檔案就可以了,開始整合操作:
(1).解壓jiangdx-stream-master.zip檔案後,將jiangdx-stream-master\stream\src\main資料夾下的java目錄整個拷貝到你的專案src中。 (2)解壓stream-1.8.1.10157.war後,開啟資料夾,將除了META-INF ,WEB-INF不拷貝其他全部拷貝到自己工程專案的WEB-INF目錄下. (3).新增jar包,將stream-1.8.1.10157\WEB-INF\lib 下的所有jar包以及stream-1.8.0.10076-r.jar,json-20090211.jar拷貝放置到自己工程的lib下     到這裡基本最簡單的檔案上傳就搭建好了,開啟tomcat伺服器,瀏覽器輸入地址,http://127.0.0.1:8080/stream/index.html,進入上傳頁面,即可進行檔案上傳,這是官方的指導方法,實際上按照上面的做法並不能進行上傳,至少IE還是不能進行上傳,這裡說一下解決的方法:
  a:    修改url地址 swfURL : "/swf/FlashUploader.swf", 改為相對地址:swfURL : "swf/FlashUploader.swf",  tokenURL : "/tk",改為相對地址:tokenURL : "tk",
frmUploadURL : "/fd", 改為相對地址:frmUploadURL : "fd",
uploadURL : "/upload", 改為相對地址:uploadURL : "upload",
 
b:   最後一個引數結尾不要加逗號   var config = {     .....第一個引數......,
    ......第二個引數..... ,     ......第N個引數...... } 注意最後一個引數不要以,號結尾,否則IE下就不能執行了。 以上修改好後即可進行上傳操作,檔案儲存的路徑在 stream-config.properties 配置中。   雖然以上配置好了可以進行上傳操作,但是遠遠不能滿足公司實際使用的要求,比如防止檔案衝突,對上傳的檔案進行重新命名操作同時儲存實際檔名至資料庫,配置資料庫連線池,上傳限速,應用上傳分離中的跨域上傳,於是這裡是本人原創的做法,不一定就是最好的,但是可以借鑑使用。 這裡採用了spring MVC  + spring  + hibernate  + stream外掛進行整合在一起。 (第二種 )修改後具有的特點:SSH框架整合,檔案防衝突,回傳檔案資訊至前臺,上傳介面美化,上傳限速,跨域上傳,相容IE6-IE9 : 為了讓大家更好的瞭解這個上傳問題,這裡貼出了我的程式碼地址:http://download.csdn.net/detail/qq_27063119/9630240  (6個金幣下載,大家支援一下好吧,打這麼多字不容易啊,實在沒有金幣就  至我郵件  [email protected](不一定能夠及時回覆,請諒解!)) (1)首先還是搭建好上傳檔案的專案以支援跨域上傳,使用spring MVC+spring+hibernate的框架,以及一個測試的專案(隨便用什麼搭建,建議使用最簡單的jsp+servlet),搭建完畢後,效果是,啟動兩個專案,當然兩個專案可以放置到兩臺機器上,只要兩臺機器可以ping通就可以, streamSH專案結構如圖所示:
ceshi專案結構如圖所示:
看了上面的結構,大家應該有所瞭解了吧,其中streamSH中的TokenController可以去掉,因為跨域上傳,token碼是由應用伺服器生成的,所以要放到ceshi專案中。當然stream有自己的配置檔案文件上說可以進行跨域上傳,但是我試了好久發現不好用,於是自己改寫了,在streamSH專案上加了過濾器進行新增頭資訊
public class SecurityFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response, FilterChain chain)throws ServletException, IOException {
System.out.println("********************跨域**********************");
System.out.println("=========="+request.getMethod()+"============"+request.getHeader("Access-Control-Request-Method"));
if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
System.out.println("===================新增標頭檔案===================");
response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            response.addHeader("Access-Control-Allow-Headers", "Content-Range,Content-Type");
            response.addHeader("Access-Control-Max-Age", "1800");//30 min
        }
chain.doFilter(request, response);
    }
}


並且每個controller都會對request以及response進行新增頭資訊 即在controller中呼叫doOptions()方法
@RequestMapping(method=RequestMethod.GET,value="/upload")
public void doGet(HttpServletRequest req,HttpServletResponse resp) throws IOException{
doOptions(req, resp);
.
.
.
}


protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException{
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json;charset=utf-8");
resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Headers", "Content-Range,Content-Type");
resp.setHeader("Access-Control-Allow-Origin", Configurations.getCrossOrigins());
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
}


(2)上傳介面美化,如下圖所示,這裡我改動了js以及css樣式以及iframe的介面,具體可以參考我的程式碼,
 這裡順帶提一下,測試跨域上傳時候,如果兩個專案放在本機同一個伺服器下,建議使用http://127.0.0.1:8080 開頭或者  http://localhost:8080,不然即使不能夠跨域上傳,但是測試不出來, (3)上傳限速問題       其實限速原理很簡單,也就是while迴圈寫入資料時候,加上Thread.sleep(XXX);就達到了限速目的,這裡我在配置檔案中加了一句   STREAM_UPLOAD_SPEED=1500   (及1.5MB/S),  後臺拿到這個資料後,需要進行操作,  真正的休眠時間為:7500/(STREAM_UPLOAD_SPEED數字);   這個是我的機器測試測出來的,可以自行計算填寫的,然後flax上傳時,休眠時間為  (7500/(STREAM_UPLOAD_SPEED數字))/2,不要問為什麼,我也是測出來的。
(4)相容IE6-IE9     為了相容IE6-IE9,需要使用flash進行上傳,當然不跨域時候比較容易的,跨域了,就會麻煩,比如:IE7跨域上傳時候,tolenURL  必須為應用伺服器的controller或者servlet的地址,否則上傳不了,這裡弄好了過後,你會發現還是上傳不了的,因為flash跨域時候會請求跨域伺服器的crossdomain.xml檔案,這個檔案要放到 tomcat的根目錄下,也就是webapps\ROOT目錄下,如果發現沒有這個目錄,那你應該是使用myeclipse了,這裡舉個例子:放到workspace\.metadata\.me_tcat7\webapps目錄下  ,然後在server.xml的<Host></Host>中新增 <Context path="" docBase="D:\\myeclipse\\workspace\\.metadata\\.me_tcat7\\webapps\\" reloadable="true"  /> 這樣一段話即可,  不管你怎樣弄,只要能夠使保證用檔案伺服器的地址 加上crossdomain.xml,如http://192.168.1.141:8080/crossdomain.xml 能夠訪問到檔案就可以了。這裡一定要注意啊!!!!! (5)檔案防止衝突 因為使用者上傳的檔案可能會重名,那麼直接儲存會導致覆蓋檔案,為了避免檔案上傳的衝突,於是我們要使用UUID對檔案進行重新命名,並且將檔案的真實名字以及UUID,檔案路徑都儲存到資料庫中,同時將UUID 以及 檔案真實的名字 回傳到前臺,前臺接受資料 通過 onComplete : function(file) {

}   //每次上傳成功一個檔案後都會呼叫
函式進行接收的,所有自定義返回的引數都放在了msg中,如下所示可以取出name和uuid的值。 var msg = eval("(" + file.msg + ")");
console.info(msg.map.name+"    "+msg.map.uuid);
這裡還要說一點,先前我是將檔案直接快取到當前年月日的目錄下,這樣可以降低伺服器在移動檔案損耗的效能,但是後來發現,如果使用者上傳的檔案過大,跨過了晚上12點,因為是分段上傳的,12點後上傳的檔案會放置到新的年月日資料夾中,那麼則會出現12點後的檔案銜接不上12點之前上傳的部分檔案了, 這樣會導致失敗, 於是後來犧牲了效能,將所有上傳的檔案先都快取在一個固定目錄下,然後上傳完畢後移動到當前的年月日資料夾下。不一定是好的辦法,暫時這樣用了。 為了讓大家更好的瞭解這個上傳問題,這裡貼出了我的程式碼地址:http://download.csdn.net/detail/qq_27063119/9630240  (6個金幣下載,大家支援一下好吧,打這麼多字不容易啊,實在沒有金幣就  至我郵件  [email protected](不一定能夠及時回覆,請諒解!))
到這裡基本就講完了,謝謝大家!!!

相關推薦

no