现在的位置: 首页 > 综合 > 正文

IOS文件的上传与下载(二)

2017年12月07日 ⁄ 综合 ⁄ 共 14818字 ⁄ 字号 评论关闭


上篇博文讲解了一下IOS文件的上传,下面来说一下文件的下载(对于文件的上传与下载在客户端有些代码是重复的)
首先说一下文件下载的服务端代码,有多种方法可以实现文件的下载,如下:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;

namespace webdownloadupload
{
    /// <summary>
    /// 处理文件的下载 downloadfile.ashx
    /// </summary>
    public class DownloadFileHandler : IHttpHandler
    {

        public string DOWNLOAD_PATH = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["DownloadPath"]);
        private const int BUFFER_LEN = 8192;
        //建议使用HandlerHeaderDownLoadFile或者HandlerDownLoadFileThree方式实现下载
        public void ProcessRequest(HttpContext context)
        {
            string filename = context.Request.Params["filename"];
           
            if (String.IsNullOrEmpty(filename))
            {
                filename = context.Request.Headers["filename"];
                if (String.IsNullOrEmpty(filename))
                {
                    long len = context.Request.InputStream.Length;

                    byte[] b = new byte[len];
                    //可以自定义数据结构来这里实现数据的解析
                    
                    context.Request.InputStream.Read(b, 0, b.Length);

                    String result = System.Text.Encoding.Default.GetString(b);
                    

                    //在客户端以数据流的方式传递过来
                    JavaScriptSerializer Serializer = new JavaScriptSerializer();
                   Dictionary<Object,Object> obj =  Serializer.Deserialize<Dictionary<object, object>>(result);
                   foreach (object o in obj.Keys)
                   {
                       context.Request.Headers.Add(o.ToString(), obj[o].ToString());
                       //context.Request.Form.Add(o.ToString(), obj[o].ToString());//只读的
                       //context.Request.Params.Add(o.ToString(), obj[o].ToString());//只读的
                   }

                   HandlerHeaderDownLoadFile(context);
                }
                else
                {
                    HandlerHeaderDownLoadFile(context);
                }
            }
            else
            {
                HandlerParamsDownLoadFile(context);
            }
            
        }
        //NSFileHandler
        private void HandlerHeaderDownLoadFile(HttpContext context)
        {

            long len = context.Request.InputStream.Length;

            byte[] b = new byte[len];
            context.Request.InputStream.Read(b, 0, b.Length);

           String result = System.Text.Encoding.Default.GetString(b);

            context.Response.Clear();
            context.Response.AddHeader(@"content-type", @"application/octet-stream");
            string filename = context.Request.Headers["filename"];
            if (String.IsNullOrEmpty(filename))
            {
                context.Response.Write("{\"result\":\"failed\",\"message\":\"filename is null\"}");
                context.Response.End();
                return;
            }
            context.Response.AddHeader("Content-Disposition", "attachement;filename=" + filename);
            context.Response.AddHeader("filename", filename);
            String fullfilename = String.Format("{0}{1}", DOWNLOAD_PATH, filename);
            byte[] buffer = new byte[BUFFER_LEN];
            try
            {
                using (FileStream fs = new FileStream(fullfilename, FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    context.Response.AddHeader(@"Content-Length", fs.Length.ToString());
                    int length = 0;
                    while ((length = fs.Read(buffer, 0, BUFFER_LEN)) > 0)
                    {
                        context.Response.OutputStream.Write(buffer, 0, length);
                    }
                }
            }
            catch (Exception ex)
            {
                context.Response.Write("{\"result\":\"failed\",\"message\":\""+ex.Message+"\"}");
                context.Response.End();
            }
            context.Response.Write("{\"result\":\"success\",\"message\":\"\"}");
            context.Response.Flush();
            context.Response.End();

        }
        /// <summary>
        /// 写不同的方法只是为了测试下,个人建议使用HandlerDownLoadFileThree方式下载
        /// </summary>
        /// <param name="context"></param>
        private void HandlerParamsDownLoadFile(HttpContext context)
        {
            int downloadtype = Convert.ToInt32(context.Request.Params["downloadtype"]);

            switch (downloadtype)
            {
                case 0:
                    HandlerDownLoadFileZero(context);
                    break;
                case 1:
                    HandlerDownLoadFileOne(context);
                    break;
                case 2:
                    HandlerDownLoadFileTwo(context);
                    break;
                case 3:
                case 5:
                    HandlerDownLoadFileThree(context);
                    break;
                case 4:
                    HandlerDownLoadFileFour(context);
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        ///   之前一直用这种下载方式,可是有一次用户上传了一个700Mb的文件时报内存溢出的问题,
        /// 分析了一下原因,用户的内存只有256M,而下载文件时要创建内存流,导致了内存溢出。
        /// </summary>
        /// <param name="context"></param>
        private void HandlerDownLoadFileZero(HttpContext context)
        {
            string filename = context.Request.Params["filename"];
            context.Response.ClearHeaders();
            context.Response.Clear();
            context.Response.Expires = 0;
            context.Response.Buffer = true;
            String path = String.Format("{0}{1}",DOWNLOAD_PATH,filename);

            FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
            byte[] bytes = null;
            if (stream.Length == 0)
            {
                bytes = new byte[1];
            }
            else {
                bytes = new byte[stream.Length];
            }
            stream.Read(bytes, 0, (int)bytes.Length);
            stream.Close();
            context.Response.AddHeader("Content-Disposition", "attachment;file=" + filename);
            context.Response.ContentType = "application/octet-stream;charset=utf-8";
            context.Response.BinaryWrite(bytes);
            context.Response.End();
        }

        /// <summary>
        /// TransmitFile 实现下载
        /// </summary>
        /// <param name="context"></param>
        private void HandlerDownLoadFileOne(HttpContext context)
        {
            /*
            微软为Response对象提供了一个新的方法TransmitFile来解决使用Response.BinaryWrite
            下载超过400mb的文件时导致Aspnet_wp.exe进程回收而无法成功下载的问题。
            代码如下:
            */
            context.Response.AddHeader("Content-Type", "z-rar-compressed");
            string filename = context.Request.Params["filename"];
            context.Response.AddHeader("Content-Disposition", "attachment;filename="+filename);

            string filepath = string.Format("{0}{1}", DOWNLOAD_PATH, filename);
            context.Response.TransmitFile(filepath);
        }
        /// <summary>
        /// WriteFile下载
        /// </summary>
        /// <param name="context"></param>
        private void HandlerDownLoadFileTwo(HttpContext context)
        {
            string filename = context.Request.Params["filename"];
            string filepath = string.Format("{0}{1}", DOWNLOAD_PATH, filename);
            FileInfo fileinfo = new FileInfo(filepath);
            context.Response.Clear();
            context.Response.ClearContent();
            context.Response.ClearHeaders();
            context.Response.AddHeader("Content-Disposition", "attachment;filename="+filename);
            context.Response.AddHeader("Content-Length", fileinfo.Length.ToString());
            context.Response.AddHeader("Content-Transfer-Encoding", "binary");
            context.Response.AddHeader("Content-Type", "application/octet-stream");
            context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
            context.Response.WriteFile(fileinfo.FullName);
            context.Response.Flush();
            context.Response.End();
        }
        /// <summary>
        /// WriteFile分块下载
        /// </summary>
        /// <param name="context"></param>
        private void HandlerDownLoadFileThree(HttpContext context)
        {
            string filename = context.Request.Params["filename"];
            string filepath = string.Format("{0}{1}", DOWNLOAD_PATH, filename);
            FileInfo fileinfo = new FileInfo(filepath);
            if (fileinfo.Exists)
            {
                const long chunksize = 102400;//每次读取100K
                byte[] buffer = new byte[chunksize];
                context.Response.Clear();

                FileStream stream = File.OpenRead(filepath);
                long dataLengthToRead = stream.Length;//获取下载文件的大小
                context.Response.ContentType = "application/octet-stream";
                context.Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
                while (dataLengthToRead > 0 && context.Response.IsClientConnected)
                {
                    int lengthRead = stream.Read(buffer, 0, Convert.ToInt32(chunksize));
                    context.Response.OutputStream.Write(buffer, 0, lengthRead);
                    context.Response.Flush();
                    dataLengthToRead = dataLengthToRead - lengthRead;
                }
            }
            context.Response.Close();
        }
        /// <summary>
        /// 流方式下载
        /// </summary>
        /// <param name="context"></param>
        private void HandlerDownLoadFileFour(HttpContext context)
        {
            string filename = context.Request.Params["filename"];
            string filepath = string.Format("{0}{1}", DOWNLOAD_PATH, filename);

            FileStream fs = new FileStream(filepath, FileMode.Open);
            byte[] bytes = new byte[(int)fs.Length];
            fs.Read(bytes, 0, bytes.Length);
            fs.Close();
            context.Response.ContentType = "application/octet-stream";
            context.Response.AddHeader("Content-Disposition", "attachment;filename =" + filename);
            context.Response.BinaryWrite(bytes);
            context.Response.Flush();
            context.Response.End();
        }

        

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

以后就是服务端代码的全部,写的不完善的地方,欢迎大家批评指正,下面来说可以端的代码,如下图:

#pragma mark 生成唯一的文件名
-(NSString *)GenerateFileName{
    int seed = arc4random();
    
    NSDate *date =[NSDate date];
    NSTimeInterval sec =[date timeIntervalSinceNow];
    NSDate *currentDate =[[NSDate alloc] initWithTimeIntervalSinceNow:sec];
    
    NSDateFormatter *df =[[NSDateFormatter alloc] init];
    
    [df setDateFormat:@"yyyyMMddHHmmsssss"];
    
    NSString *fileName =[NSString stringWithFormat:@"%@%d%@",[df stringFromDate:currentDate],seed,@".rar"];
    
    return fileName;

}
#pragma mark 获取一个随机数,范围[from,to)
-(int)getRandomNumber:(int)from to:(int)to{
    return (int)(from +(arc4random()%(to-from+1)));
}

#pragma mark 下载文件一
-(void)BtnDownLoadFileMannerOne:(id)sender{
    
    NSString *targetfilename = [self GenerateFileName];
    int index = [self getRandomNumber:0 to:5];
    NSString *sourcefilenaame = [self.sourceArray objectAtIndex:index];
    //通过GET方式传递参数
    NSString *downloadurlparams = [downloadurl stringByAppendingFormat:@"?filename=%@&downloadtype=%d",sourcefilenaame,index];
    NSURL *UrlServer =[NSURL URLWithString:downloadurlparams];
    NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:UrlServer];
    
    [request setHTTPMethod:@"GET"];
    
    [request setValue:sourcefilenaame forHTTPHeaderField:@"filename"];
    
    [request setHTTPMethod:@"POST"];
    
    NSString *postMsg =[NSString stringWithFormat:@"message=%@",@"hello"];
    
    NSData *postData =[postMsg dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    
    [request setHTTPBody:postData];
    FileUploadDelegate *delegate =[[FileUploadDelegate alloc] init];
    delegate.direction = TRANSFER_DOWNLOAD;
    NSArray *pathArray =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    
    
    delegate.target =[[pathArray objectAtIndex:0] stringByAppendingPathComponent:targetfilename];
    
   delegate.connection = [NSURLConnection connectionWithRequest:request delegate:delegate];
    
}

#pragma mark 下载文件二
-(void)BtnDownLoadFileMannerTwo:(id)sender{
    //POST方式传递参数
    NSString *targetfilename = [self GenerateFileName];
    int index = [self getRandomNumber:0 to:5];

    NSString *sourcefilenaame = [self.sourceArray objectAtIndex:index];
    NSURL *UrlServer =[NSURL URLWithString:downloadurl];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:UrlServer];
    [request setHTTPMethod:@"POST"];
    NSString *postMsg =[NSString stringWithFormat:@"filename=%@&downloadtype=%d",sourcefilenaame,index];
    NSData *postData = [postMsg dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    [request setHTTPBody:postData];
    FileUploadDelegate *delegate =[[FileUploadDelegate alloc] init];
    delegate.direction = TRANSFER_DOWNLOAD;
    NSArray *pathArray =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    delegate.target =[[pathArray objectAtIndex:0] stringByAppendingPathComponent:targetfilename];
    
    delegate.connection = [NSURLConnection connectionWithRequest:request delegate:delegate];

}

#pragma mark 下载文件三
-(void)BtnDownLoadFileMannerThree:(id)sender{
    NSString *targetfilename = [self GenerateFileName];
    int index = [self getRandomNumber:0 to:5];
    NSString *sourcefilenaame = [self.sourceArray objectAtIndex:index];
    NSURL *UrlServer =[NSURL URLWithString:downloadurl];
    //GET 通过Header传递参数
    
    NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:UrlServer];
    [request setValue:sourcefilenaame forHTTPHeaderField:@"filename"];
    [request setValue:[NSString stringWithFormat:@"%d",index] forHTTPHeaderField:@"downloadtype"];
    FileUploadDelegate *delegate =[[FileUploadDelegate alloc] init];
    delegate.direction = TRANSFER_DOWNLOAD;
    NSArray *pathArray =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    delegate.target =[[pathArray objectAtIndex:0] stringByAppendingPathComponent:targetfilename];
    
    delegate.connection = [NSURLConnection connectionWithRequest:request delegate:delegate];
}

#pragma mark 下载文件四
-(void)BtnDownLoadFileMannerFour:(id)sender{
    
    
    NSString *targetfilename = [self GenerateFileName];
    int index = [self getRandomNumber:0 to:5];
    NSString *sourcefilenaame = [self.sourceArray objectAtIndex:index];
    NSURL *UrlServer =[NSURL URLWithString:downloadurl];
    
    NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:UrlServer];
    //POST 方式,转换为Array转换为JSON字符串
    NSMutableDictionary *dic =[NSMutableDictionary dictionary];
    [dic setObject:sourcefilenaame forKey:@"filename"];
    [dic setObject:[NSString stringWithFormat:@"%d",index] forKey:@"downloadtype"];
   
    NSString *httpBodyString = [[[SBJson4Writer alloc] init] stringWithObject:dic];
   
    NSData *bodyData =[httpBodyString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    [request setHTTPMethod:@"POST"];
    
 
    [request setHTTPBody:bodyData];
    
    
    FileUploadDelegate *delegate =[[FileUploadDelegate alloc] init];
    delegate.direction = TRANSFER_DOWNLOAD;
    NSArray *pathArray =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    delegate.target =[[pathArray objectAtIndex:0] stringByAppendingPathComponent:targetfilename];
    delegate.connection = [NSURLConnection connectionWithRequest:request delegate:delegate];
    
}

FileUploadDElegate的代码看上篇博文,这个不在重复

服务端代码下载

客户端代码下载

抱歉!评论已关闭.