struts 2では、アクションを通じてInputStreamのダウンロードファイルとiOS及びAndroid端末で受信したインプリメンテーションを行います.

7813 ワード

最近はモバイル開発の中でいくつかのファイルのダウンロードの問題に出会いました.実現したら、わざわざ記録して、後で調べます.
最も簡単なダウンロードの実現方法は、ファイルのURLを直接携帯電話に送信し、携帯電話がURLを通じてこのファイルを要求することであり、要求したユーザを正確に検証することができないという欠点がある.もう一つの方法は、アクションによって、まずユーザの識別情報を検証してから、ハンドヘルドデバイス(要求側)にファイルを送信することである.次に第二中方式を実現します.
 
  • サーバー側はとても簡単です.つまり、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;//           4096
    
    		while((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();
    
    	}
    
    }