zoukankan      html  css  js  c++  java
  • struts2中通过Action以InputStream的下载文件以及在iOS以及Android端接收的实现方式

    最近在移动开发中遇到了一些文件下载的问题,实现后特地记录一下,以备以后查阅。

    最简单的下载的实现方式是将文件的在网络上的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;//最后一次的长度可能不足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();
    	}
    }
    

     

      

     

  • 相关阅读:
    java基础数据
    Java环境搭建
    Mysql数据库基础
    php环境搭建
    1117bootstrap组件
    1117bootstrap
    1115表单验证
    1114JS实例4
    1113JS实例3
    1111JS实例2
  • 原文地址:https://www.cnblogs.com/janken/p/2534977.html
Copyright © 2011-2022 走看看