NSURLSessionUploadTask 不使用 POST 上传图片
NSURLSessionUploadTask not uploading image using POST
我有以下 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 代码对我和 returns 不起作用
'msg1'=>'file array is empty'
我正在使用从图库中选择图片并尝试上传它。
#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
请让我知道我的目标代码中缺少哪一部分
这是一个简短的列表:
- 您需要在每个块中包含 Content-Type 和 Content-Disposition headers。 (你原本两者都有,但被注释掉了。)
- 每组 headers 必须以 两对
\r\n
对结尾,而不是一对。 (原代码在这方面是正确的,但注释掉了。)
- 您最初使用表单字段名称 "photo" 而不是 "image" 作为 Android 和 PHP 代码所使用的附加它。现在这是正确的。
- 一开始就不需要在请求上设置Content-Length;该任务会为您完成。
- 您的脚本需要上传两个文件,而您只附加了一个。
这可能是一个不完整的列表,因此即使您修复了它们,也可能无法正常工作。我通常建议开发人员跳过 form-data 编码并使用 URL 编码来上传是有原因的。它的效率有点低,但它更容易编写很多。 :-)
无论如何,我强烈建议您使用 运行 Charles Proxy 并将网络浏览器或您的 Android 应用程序指向它并查看发送的内容,然后对 iOS,比较两者。这应该会使大多数或所有错误更容易被发现。
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
我有以下 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 代码对我和 returns 不起作用 'msg1'=>'file array is empty'
我正在使用从图库中选择图片并尝试上传它。
#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
请让我知道我的目标代码中缺少哪一部分
这是一个简短的列表:
- 您需要在每个块中包含 Content-Type 和 Content-Disposition headers。 (你原本两者都有,但被注释掉了。)
- 每组 headers 必须以 两对
\r\n
对结尾,而不是一对。 (原代码在这方面是正确的,但注释掉了。) - 您最初使用表单字段名称 "photo" 而不是 "image" 作为 Android 和 PHP 代码所使用的附加它。现在这是正确的。
- 一开始就不需要在请求上设置Content-Length;该任务会为您完成。
- 您的脚本需要上传两个文件,而您只附加了一个。
这可能是一个不完整的列表,因此即使您修复了它们,也可能无法正常工作。我通常建议开发人员跳过 form-data 编码并使用 URL 编码来上传是有原因的。它的效率有点低,但它更容易编写很多。 :-)
无论如何,我强烈建议您使用 运行 Charles Proxy 并将网络浏览器或您的 Android 应用程序指向它并查看发送的内容,然后对 iOS,比较两者。这应该会使大多数或所有错误更容易被发现。
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