前言
本篇博文要解决的问题正如题目所示, 我在开发一个项目的时候遇到这个问题, 开始什么都不会, 在网上各种百度各种爬楼, 都是只有一部分内容, 根本帮助不了我完成问题, 经过几天的查询和学习, 最终找到了一个方法, 这里我就给出我的方法, 不是唯一的,不是经善尽美的, 还望大神不要喷, 希望能给需要的朋友带来帮助. 好的, 下面直接上内容(请耐心看代码, 我亲测成功!如有问题联系我, 咱们讨论讨论^_^)
iOS端功能实现
这里借助框架AFNetworking来实现iOS端的功能, 可以在github上找到最新版AFNetworking
1> 修改AFHTTPRequestOperationManager.h文件, 在最后自定义一个方法, 参数使用主要就看这里了, 后边不在赘述.
/**
* 自定义用来向后台发送多张图片的方法
*
* @param url 后台接口URL
* @param images 图片数组, 内容是UIimage
* @param parameter 一个参数, 我在这里提供的参数是后台在接收时的凭据
* @param parameters 字典内容就是和正常AFN向后台post参数是一样的根据需要填写内容
* @param successBlock 图片上传后台成功回调的block
* @param failureBlock 图片上传后台失败回调的block
* @param uploadProgressBlock 图片上传过程中调用的block, 用来实现进度条
*/
- (void)startMultiPartUploadTaskWithUrl:(NSString *)url imagesArray:(NSArray *)images parameterOfimages:(NSString *)parameter parametersDict:(NSDictionary *)parameters compressionRation:(float)ratio successBlock:(void(^)(id operation, id responseObject))successBlock failureBlock:(void(^)(id operation, NSError *error))failureBlock uploadProgressBlock:(void(^)(float uploadPercent, long long totalByteWritten, long long totalByteExpectedToWrite))uploadProgressBlock;
2> 在AFHTTPRequestOperationManager.m中实现自定义的方法
- (void)startMultiPartUploadTaskWithUrl:(NSString *)url imagesArray:(NSArray *)images parameterOfimages:(NSString *)parameter parametersDict:(NSDictionary *)parameters compressionRation:(float)ratio successBlock:(void (^)(id, id responseObject))successBlock failureBlock:(void (^)(id, NSError *))failureBlock uploadProgressBlock:(void (^)(float, long long, long long))uploadProgressBlock {
if (images.count == 0) {
NSLog(@"上传内容中图片数为0");
return;
}
for (int i=0; i<images.count; i++) {
if (![[images objectAtIndex:i] isKindOfClass:[UIImage class]]) {
NSLog(@"第%d个元素不是图片", i+1);
return;
}
}
AFHTTPRequestOperationManager *myManager = [[self class] manager];
myManager.responseSerializer = [AFHTTPResponseSerializer serializer];
[myManager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
int i = 0;
// 根据当前系统时间生成图片名称
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyyMMddHHmmss"];
NSString *dateString = [formatter stringFromDate:date];
for (UIImage *imageTmp in images) {
// 修改图片大小
UIImage *image = [imageTmp transformWidth:50.0f height:50.0f];
NSString *fileName = [NSString stringWithFormat:@"%@_%d.png", dateString, i];
NSData *imageData;
if (ratio>0.0f && ratio<1.0f) {
imageData = UIImageJPEGRepresentation(image, ratio);
} else {
imageData = UIImageJPEGRepresentation(image, 1.0f);
}
// NSLog(@"imagedata=%@", imageData);
// 这个地方有个注意点, 就是那个@"%@[]", 这个[] 是必须的, 它告诉后台我传送的是多张图片
[formData appendPartWithFileData:imageData name:[NSString stringWithFormat:@"%@[]", parameter] fileName:fileName mimeType:@"image/jpeg/png/jpg"];
i++;
}
// NSLog(@"body=%@", formData);
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
successBlock(operation, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// NSLog(@"图片上传失败:%@", error);
failureBlock(operation, error);
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] init];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
CGFloat percent = totalBytesWritten*1.0 / totalBytesExpectedToWrite;
uploadProgressBlock(percent, totalBytesWritten, totalBytesExpectedToWrite);
}];
}
3> 在某处调用这个方法
// 首先先实例化这个manager呗
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
/**
* _itemsSectionPictureArray就是图片数组
* test 对应PHP理解它的用途
*/
[manager startMultiPartUploadTaskWithUrl:urlStr_images
imagesArray:_itemsSectionPictureArray
parameterOfimages:@"test"
parametersDict:@{@"helpID":(NSDictionary *)dicResponseJson[@"data"][@"helpID"]}
compressionRation:1.0f
successBlock:^(id operation, id responseObject) {
// NSString *strtmp = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
// NSLog(@"+++成功%@", strtmp);
}
failureBlock:^(id operation, NSError *error) {
NSLog(@"---失败");
}
uploadProgressBlock:^(float uploadPercent, long long totalByteWritten, long long totalByteExpectedToWrite) {
NSLog(@"***%lf", uploadPercent);
}];
PHP端功能实现(这个就是那个处理接口)
<?php
header("Content-type:application/octet-stream"); //这句告诉以流的形式来接收数据;
// 这个是iOS端通过parameters传递过来的参数
$helpID = $_POST['helpID'];
// 这里的test就是parameter传递过来的参数
$file = $_FILES['test'];
for ($i=0; $i<count($_FILES['test']['error']); $i++) {
if ($_FILES['test']['error'][$i] == 0) {
//这里在同目录下需要有pictures文件夹
if(move_uploaded_file($_FILES['test']['tmp_name'][$i], '/pictures/'.$_FILES['test']['name'][$i])) {
echo json_encode(array("status"=>1, "message"=>"图片上传成功", "success"=>"true", "data"=>array($file)));
} else {
echo json_encode(array("status"=>1, "message"=>"图片不可移动", "success"=>"false", "data"=>array($file)));
}
}
}
?>
小编遇到的问题
1> 后台PHP获取不到值
(1)首先可能是AFHTTPRequestOperationManager.m实现有错误
(2)可能是后台$_FILES的错误(要了解它接收过来的是个数组)
(3)期间还有一个问题, 不过有错误代码, 直接百度错误代码就应该能找到错误
(我好像修改了AFURLResponseSerialization.m的223行, 加上了@”text/html”, @”image/jpeg”, @”text/plain”, 这三项内容)
2> 图片文件move_uploaded_file移动不了文件
(1)可能是后台文件对要操作的文件夹没有权限
(2)可能是操作中带有中文(我刚开始传日期包含中文-纠结了一天呢)
(3)我忘了…