NSURLSessionUploadTask不使用POST上传图像

时间:2016-09-22 20:34:52

标签: nsurlsession nsurlsessionuploadtask

我有以下安卓完美的Android代码:

DefaultHttpClient client = new DefaultHttpClient(UploadPostActivity.this);
String s = "http://dacaea28.ngrok.io/my-site/multipart.php";
URL url = new URL(s);

String filepath = "/sdcard/Download/images.jpg";

File file = new File(filepath);
FileBody cbFile = new FileBody(file);


MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
org.apache.http.client.methods.HttpPost post = new org.apache.http.client.methods.HttpPost(s);

mpEntity.addPart("image",cbFile);

mpEntity.addPart("name", new StringBody("Test", Charset.forName("UTF-8")));
mpEntity.addPart("data", new StringBody("This is test report", Charset.forName("UTF-8")));
org.apache.http.HttpResponse response = null;


post.setEntity(mpEntity);
org.apache.http.HttpResponse response1 = client.execute(post);
String t = EntityUtils.toString(response1.getEntity());

Log.d("Response:", t);

我正在使用的PHP代码:

<?php
//Receive the data from android
$name = $_POST['name'];
$data = $_POST['data'];

if(empty($_FILES))
{
echo json_encode(
            array(

                'msg1'=>'file array is empty'
                )
            );

}
else if(!isset($_FILES['image']))
{
echo json_encode(
            array(

                'msg2'=>'image is not being set'
                )
            );
}
else
{
$file = $_FILES['image'];
$file2 = $_FILES['doc'];
//echo json_encode(
//            array(
//                'result'=>'success adding $name , $data and  $file',
//                'msg'=>'Report added successfully.'
//                )
//            );
$size = $file['size'];
echo "Name is $name and file size is $size";

$info = pathinfo($file['name']);
$ext = $info['extension']; // get the extension of the file
$newname = $file['name']; 
$target = '/Applications/MAMP/htdocs/my-site/images/'.$newname;
move_uploaded_file( $file['tmp_name'], $target);
echo "Name is $name, file size is $size, extension is $ext, new file name is $newname and finally target is $target";

$size2 = $file2['size'];
echo "Name is $name and file size is $size";

$info2 = pathinfo($file2['name']);
$ext2 = $info2['extension']; // get the extension of the file
$newname2 = $file2['name']; 
$target2 = '/Applications/MAMP/htdocs/my-site/images/'.$newname2;
move_uploaded_file( $file2['tmp_name'], $target2);
echo "Name is $name, file size is $size, extension is $ext, new file name is $newname and finally target is $target";


}



?>

现在相应的iOS代码对我不起作用并返回                 'msg1'=&gt;'文件数组为空'

我正在使用从图库中选择图片并尝试上传图片。

#import "UploadViewController.h"

@interface UploadViewController ()<NSURLSessionDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation UploadViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}


- (IBAction)uploadData:(id)sender {
       const NSString *boundaryConstant = @"----------V2ymHFg03ehbqgZCaKO6jy";
const NSString *fileParamConstant = @"image";

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];

NSURL* requestURL = [NSURL URLWithString:@"http://dacaea28.ngrok.io/my-site/multipart.php"];


NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:requestURL];
[request setHTTPMethod:@"POST"];

NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundaryConstant];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];

NSMutableData *body = [NSMutableData data];


NSData *imageData = UIImageJPEGRepresentation(self.imageView.image,0.9);

//    NSLog(@"image data added %lu",self.imageView.image.size);

if (imageData) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
                [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fileParamConstant, @"filename"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:imageData];
    [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}

        [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];

        NSString *postLength = [NSString stringWithFormat:@"%zu", [body length]];
        [request setValue:postLength forHTTPHeaderField:@"Content-Length"];

        [request setHTTPBody:body];
    [request addValue:@"Test" forHTTPHeaderField:@"name"];

    [request addValue:@"Test2" forHTTPHeaderField:@"data"];

        NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSLog(@"STRING %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
            NSLog(@"%@", response);
            NSLog(@"%@", error);
        }];
        [uploadTask resume];
}



- (IBAction)pickImage:(id)sender {

    UIImagePickerController *pickerController = [[UIImagePickerController alloc]
                                                 init];
    pickerController.delegate = self;
    [self presentViewController:pickerController animated:YES completion:nil];
}


- (void) imagePickerController:(UIImagePickerController *)picker
         didFinishPickingImage:(UIImage *)image
                   editingInfo:(NSDictionary *)editingInfo
{
    self.imageView.image = image;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

请告诉我我的objc代码中缺少的部分

2 个答案:

答案 0 :(得分:0)

这是一个简短的清单:

  • 您需要在每个块中包含两个 Content-Type Content-Disposition标头。 (你最初都有,但注释掉了。)
  • 每组标头必须以两个 \r\n对结束,而不是一对。 (原始代码在这方面是正确的,但注释掉了。)
  • 您最初使用表单字段名称“photo”而不是“image”附加它,因为Android和PHP代码正在使用它。现在这是正确的。
  • 首先不需要在请求中设置Content-Length;任务为你做到了。
  • 您的脚本需要上传两个文件,而您只需附加一个文件。

这可能是一个不完整的列表,所以即使你修复它们,这可能也行不通。我通常建议开发人员跳过表单数据编码并使用URL编码代替上传。效率稍低,但写入的很多更简单。 : - )

无论如何,我强烈建议您运行Charles Proxy并指向网络浏览器或Android应用程序并查看发送内容,然后对iOS执行相同操作,并对两者进行比较。这应该会使大多数或所有错误更容易被发现。

答案 1 :(得分:0)

My final working code so I can find it later:

#import "UploadViewController.h"

@interface UploadViewController ()<NSURLSessionDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation UploadViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}


- (IBAction)uploadData:(id)sender {
    const NSString *boundaryConstant = @"----------V2ymHFg03ehbqgZCaKO6jy";
    const NSString *fileParamConstant = @"image";

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];

    NSURL* requestURL = [NSURL URLWithString:@"http://d7e79f94.ngrok.io/my-site/multipart.php"];


    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:requestURL];
    [request setHTTPMethod:@"POST"];

    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundaryConstant];
    [request setValue:contentType forHTTPHeaderField:@"Content-Type"];

    NSMutableData *body = [NSMutableData data];


    NSData *imageData = UIImageJPEGRepresentation(self.imageView.image,0.9);

    //    NSLog(@"image data added %lu",self.imageView.image.size);

    if (imageData) {
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fileParamConstant, @"image.jpg"] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

        [body appendData:imageData];
        [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    }

    [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];

    NSString *postLength = [NSString stringWithFormat:@"%zu", [body length]];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];

    [request setHTTPBody:body];
    [request addValue:@"Test" forHTTPHeaderField:@"name"];

    [request addValue:@"Test2" forHTTPHeaderField:@"data"];

    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"STRING %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        NSLog(@"%@", response);
        NSLog(@"%@", error);
    }];
    [uploadTask resume];
}



- (IBAction)pickImage:(id)sender {

    UIImagePickerController *pickerController = [[UIImagePickerController alloc]
                                                 init];
    pickerController.delegate = self;
    [self presentViewController:pickerController animated:YES completion:nil];
}


- (void) imagePickerController:(UIImagePickerController *)picker
         didFinishPickingImage:(UIImage *)image
                   editingInfo:(NSDictionary *)editingInfo
{
    self.imageView.image = image;
    [self dismissViewControllerAnimated:NO completion:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
 #pragma mark - Navigation

 // In a storyboard-based application, you will often want to do a little preparation before navigation
 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
 // Get the new view controller using [segue destinationViewController].
 // Pass the selected object to the new view controller.
 }
 */

@end