struts2中通過Action以InputStream的下載檔案以及在iOS以及Android端接收的實現方式

來源:互聯網
上載者:User

最近在移動開發中遇到了一些檔案下載的問題,實現後特地記錄一下,以備以後查閱。

最簡單的下載的實現方式是將檔案的在網路上的URL直接發送給手機,然後手機通過URL來請求這個檔案,這麼做有個缺點無法對請求的使用者進行準確的驗證。另一種方法是通過Action先對使用者的身分識別驗證通過後再傳送檔案給手持功能(請求端)。下面就來實現第二中方式。

 

  • 伺服器端非常簡單,就是寫個xml的設定檔,和實現一個簡單的action即可。

struts.xml的設定檔如下:

<result name="download" type="stream">  <param name="contentType">application/octet-stream</param>  <param name="inputName">targetFile</param>  <param name="contentDisposition">${suffix}</param>  <param name="contentLength">${fileSize}</param>  <param name="bufferSize">4096</param></result>

說明:

contentType:指定檔案的類型,application/octet-stream代表所有的檔案類型,查看其他的檔案類型描述;
inputName:檔案的InputStream流,action中需要提供一個返回InputStream的getTargetFile()方法;

contentDisposition:下載檔案的檔案名稱,${suffix}指到action中擷取getSuffix()方法的傳回值;也可以在這裡放置filename=${fileName},這樣通過瀏覽器訪問的時候瀏覽器會自動尋找到檔案名稱,並顯示出來;
contentLength:下載的當前檔案的大小,擷取方式同上,類型是long
bufferSize:緩衝的大小

action對象實現如下:
/**     * 檔案的輸出資料流     * @return     * @throws Exception     */    public InputStream getTargetFile() throws Exception {        java.io.File f = new java.io.File("D:\\test.avi");        if (f.exists()) {            return new FileInputStream(f);        } else {            return null;        }    }        /**     * 設定返回的檔案的名字     * @return     */    public String getFileName() {        return "test.avi";    }        /**     * 設定返回的檔案的大小     * @return     */    public long getFileSize() {        java.io.File f = new java.io.File("D:\\test.avi");        return f.length();    }        /**     * 執行請求的邏輯處理,然後根據結果來判斷是否返迴文件     * @return     */    public String download() {       //進行認證或其它的邏輯檢查        if(true){            return "download";        }        return "error";    }
  •  移動請求端實現如下:

    iOS端

網路訪問端代碼如下:

NSURL *downloadURL = [NSURL URLWithString:url];NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:downloadURL];NSHTTPURLResponse *response = nil;NSError *error = nil;NSData *resData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];if(error){      NSLog(@"請求下載檔案失敗,錯誤資訊:%@",error);      return nil;}if(resData){     if(response && [response respondsToSelector:@selector(allHeaderFields)])
   { NSDictionary *httpResponseHeaderFields = [response allHeaderFields];//獲得相應的頭 long size = [[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue];//獲得檔案的大小,是由伺服器在相應頭中傳遞過來的 NSString *fileSuffix = [httpResponseHeaderFields objectForKey:@"Content-Disposition"];//我在的伺服器端設定的存放尾碼名 VSFileUtil *fileUtil = [[VSFileUtil alloc]init];//自訂的一個檔案工具類 NSString *filePath = [fileUtil writeToFileWithNSData:resData FileName:[fileId stringByAppendingFormat:@".%@",fileSuffix]];//建立檔案 return filePath; }}

    檔案工具類的代碼如下:

NSArray *dir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);//獲得Library/Caches目錄,該目錄程式退出不會清空,iTunes也不備份此目錄NSString *cDownloadBaseFolderPath = [[dir objectAtIndex:0] stringByAppendingPathComponent:@"FMADownload"];//建立Library/Caches/FMADownload目錄作為下載目錄NSString *filePath = [cDownloadBaseFolderPath stringByAppendingPathComponent:file];//根據檔案名稱和路徑構建出檔案的絕對路徑NSFileManager *fm = [NSFileManager defaultManager];//擷取檔案管理工具[fm removeItemAtPath:filePath error:nil];//如果檔案已經存在則移除該檔案,檔案不存在時也不會拋出異常,如果想捕獲提示資訊,可以定義一個NSError傳遞給error參數即可if([data writeToFile:filePath atomically:YES])//以原子處理的方式將內容寫進檔案中{   return filePath;}else{   return nil;}

 

    Android端

    這個由於是java開發的,這個過程將變得比iOS上簡單n倍,具體代碼如下:

 

public void download() throws Exception {InputStream is = null;BufferedInputStream bis = null;FileOutputStream fos = null;BufferedOutputStream bos = null;try {httpClient = new DefaultHttpClient(new BasicHttpParams());HttpPost httpRequest = new HttpPost(validateURL);//validateURL是的請求地址HttpResponse response = httpClient.execute(httpRequest);Header[] headers = response.getAllHeaders();long size = 0;//檔案大小String suff = "";//檔案尾碼名for(Header h : headers) {if("Content-Disposition".equals(h.getName())) {suff = h.getValue();Log.i("janken", suff);} else if ("Content-Length".equals(h.getName())) {size = Long.valueOf(h.getValue());Log.i("janken", size + "");}}if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {throw new Exception("請求失敗");}HttpEntity resEntity = response.getEntity();is = resEntity.getContent();//獲得檔案的輸入資料流bis = new BufferedInputStream(is);File newFile = new File("/sdcard/test." + suff);fos = new FileOutputStream(newFile);bos = new BufferedOutputStream(fos);byte[] bytes = new byte[4096];int len = 0;//最後一次的長度可能不足4096while((len = bis.read(bytes)) > 0) {bos.write(bytes,0,len);}bos.flush();} finally {if(bis != null)bis.close();if(bos != null)bos.close();if(fos != null)fos.close();httpClient.getConnectionManager().shutdown();}}

 

  

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.