关于上传以及进度显示问题

通过HTTP的方式, 一般会采用NSURLConnection class,但往往是同步的方式来上传,比较地效率,

 

 

NSString *urlString = @"http://yourserver.com/upload.php"; 
NSString *filename = @"filename"; 
request= [[[NSMutableURLRequest alloc] init] autorelease]; 
[request setURL:[NSURL URLWithString:urlString]]; 
[request setHTTPMethod:@"POST"]; 
NSString *boundary = @"---------------------------14737809831466499882746641449"; 
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; 
[request addValue:contentType forHTTPHeaderField: @"Content-Type"]; 
NSMutableData *postbody = [NSMutableData data]; 
[postbody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
[postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@.jpg\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]]; 
[postbody appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
[postbody appendData:[NSData dataWithData:YOUR_NSDATA_HERE]]; 
[postbody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
[request setHTTPBody:postbody]; 
 
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 
returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; 
NSLog(returnString); 


一般建议还是用

ASIHttpRequest.

It is astoundingly easy - it's the most popular library on all of iOS.   Just select the "asynchronous" mode

 

一般建议还是用

ASIHttpRequest.

It is astoundingly easy - it's the most popular library on all of iOS.   Just select the "asynchronous" mode

 

[request addPostValue:file forKey:@"file"]; 或许更应该使用setData  //这里面还是有差别的,有说如果是大文件,应该使用setfile小文件或数据,就使用setdata,否则你文件打开后的数据就很大了。。。

ASIFormDataRequest *request= [[[ASIFormDataRequest alloc] initWithURL:url] autorelease]; [request setPostValue:@"Ben" forKey:@"first_name"];[request setPostValue:@"Copsey" forKey:@"last_name"];[request setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"];

 

以下的代码是给asp.net的web service用的,我们看到了viewstate的设置,否则大概要出错了

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; 
    //ADD THESE, BECAUSE ASP.NET is Expecting them for validation 
    //Even if they are empty you will be able to post the file 
    [request setPostValue:@"" forKey:@"__VIEWSTATE"]; 
    [request setPostValue:@"" forKey:@"__EVENTVALIDATION"];  
    /// 
 
    [request setFile:FIleName forKey:@"fileupload_control_Name"]; 
    [request startSynchronous]; 


默认的话。类似safari是不支持选择文件上传的。

Also note: The uploader is not supported on iOS devices (iPhone and iPad), because they lack file upload capability. This example provides a graceful degradation message for all such systems

 

这里涉及一个选项,我们并发下载的过程中是否显示下载进度,基本来说要显示进度,我们需要使用ASINetworkQUEUEs:NSOperationQuEUE(相比增加的功能就是让你track上传下载的进度)

- (IBAction)grabURLInTheBackground:(id)sender
{
   if (![self queue]) {
      [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
   }
 
   NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
   ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
   [request setDelegate:self];
   [request setDidFinishSelector:@selector(requestDone:)];
   [request setDidFailSelector:@selector(requestWentWrong:)];
   [[self queue] addOperation:request]; //queue is an NSOperationQueue
}
 
- (void)requestDone:(ASIHTTPRequest *)request
{
   NSString *response = [request responseString];
}
 
- (void)requestWentWrong:(ASIHTTPRequest *)request
{
   NSError *error = [request error];
}
 


简单来说就是:如果新加任务到ASInetworkQueue,加入的任务不会导致进度条变化,知道这个新任务被执行起来。因为ASINetworkQueue的原始实现是先请求每个Opeartion的URL获得大小,然后计算总的大小。。。。

 

When a request in an ASINetworkQueue fails, the queue will by default cancel all other requests. You can disable this behaviour with[queue setShouldCancelAllRequestsOnFailure:NO].

一般来说呢,发生一个失败后,就会取消全部,可以设置来改变这个行为的

If you are using an ASINetworkQueue to track the overall progress of several requests, overall progress will move backwards to take account of each new requestonly when that request starts running. An ASINetworkQueue will not perform a HEAD request for requests added after the queue is started, so if you are adding many requests to a running queue at once, the overall progress will not update immediately.

If a queue is already running, you do not need to call [queue go] again.

如果是人为地取消下载,那么应该调用这个:

// Cancels an asynchronous request, clearing all delegates and blocks first[request clearDelegatesAndCancel];

然后再调用request cancel,否则的话,程序会继续调用失败的delegate,实际上不是一中失败类型。。

 

直接下载数据到一个文件,文件名多写好了:::

Downloading the response directly to a file

If the resource you are requesting is fairly large, you can save memory by downloading directly to a file. This way, ASIHTTPRequest won’t have to keep the whole response in memory at once.

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"];
  • If the data is gzip compressed (see information on gzip compression), the compressed file will be uncompressed into downloadDestinationPath, and the temporary file will be deleted
  • If the data is not compressed, the temporary file is moved to downloadDestinationPath, overwriting any previous file

    这里零时目录下载结束后,会进行后续操作,包括了自动解压缩

     

    单个文件上传进度控制:

    Tracking upload progress for a single request

    In this example, myProgressIndicator is an UIProgressView.

    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
    [request setPostValue:@"Ben" forKey:@"first_name"];
    [request setPostValue:@"Copsey" forKey:@"last_name"];
    [request setUploadProgressDelegate:myProgressIndicator];
    [request startSynchronous];
    NSLog(@"Value: %f",[myProgressIndicator progress]);

     

     

    早期,还是采用集中下载/上传一个文件的方式:: 可认为取消/打断操作,选择另外一个文件操作。 。。。 下载是可以支持断点续传的,http的上传是不可以resume的,采用ftp方式倒是可能可行:

     

    HTTP in general doesn't support resuming uploads.

    I think your best approach would be to change the way you upload the file, so that you upload it in chunks.

    ie. split the file down into segments of a smaller size (eg. 256 kilobytes) and send each of them in a separate ASIFormDataRequest. Then get your server software to glue them back together.

     

     解决的办法很简单,可以按它所说的继承ASIHTTPRequest,并改写requestFinished方法。或者把所有分类情况下的finished多放在后台处理,直接改源码:

    - (void)requestFinished
    {
    #if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING
        NSLog(@"[STATUS] Request finished: %@",self);
    #endif
        if ([self error] || [self mainRequest]) {
            return;
        }
        [self reportFinished];
    }

    改完后重新构建一遍,发现至少5个下载线程时也不会影响主线程了,搞定收工~

    ===========

    ASIHTTPRequest is a wrapper that makes it alot easier to deal with HTTP requests.

    Found it here:
    http://stackoverflow.com/questions/936855/file-upload-to-http-server-in-iphone-programming

    Official website:
    http://allseeing-i.com/ASIHTTPRequest/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值