Objective-C를 사용하여 다중 파트 / 양식 데이터 POST
따라서이 HTML 코드는 데이터를 올바른 형식으로 제출합니다.
<form action="https://www.example.com/register.php" method="post" enctype="multipart/form-data">
Name: <input type="text" name="userName"><BR />
Email: <input type="text" name="userEmail"><BR />
Password: <input type="text" name="userPassword"><BR />
Avatar: <input type="file" name="avatar"><BR />
<input type="submit">
</form>
iOS에서 multipart / form-data POST를 수행하는 방법에 대한 많은 기사를 살펴 보았지만 파일 업로드뿐만 아니라 일반 매개 변수가있는 경우 수행 할 작업을 실제로 설명하는 것은 없습니다.
Obj-C에 게시하는 코드를 도와 주시겠습니까?
감사!
과정은 다음과 같습니다.
와 사전 만들기
userName
,userEmail
및userPassword
매개 변수를.NSDictionary *params = @{@"userName" : @"rob", @"userEmail" : @"rob@email.com", @"userPassword" : @"password"};
이미지의 경로를 결정합니다.
NSString *path = [[NSBundle mainBundle] pathForResource:@"avatar" ofType:@"png"];
요청을 작성하십시오.
NSString *boundary = [self generateBoundaryString]; // configure the request NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; [request setHTTPMethod:@"POST"]; // set content type NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; // create body NSData *httpBody = [self createBodyWithBoundary:boundary parameters:params paths:@[path] fieldName:fieldName];
요청 본문을 작성하기 위해 위에서 사용 된 방법입니다.
- (NSData *)createBodyWithBoundary:(NSString *)boundary parameters:(NSDictionary *)parameters paths:(NSArray *)paths fieldName:(NSString *)fieldName { NSMutableData *httpBody = [NSMutableData data]; // add params (all params are strings) [parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) { [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]]; }]; // add image data for (NSString *path in paths) { NSString *filename = [path lastPathComponent]; NSData *data = [NSData dataWithContentsOfFile:path]; NSString *mimetype = [self mimeTypeForPath:path]; [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:data]; [httpBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; } [httpBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; return httpBody; }
위의 유틸리티 방법은 다음과 같습니다.
@import MobileCoreServices; // only needed in iOS - (NSString *)mimeTypeForPath:(NSString *)path { // get a mime type for an extension using MobileCoreServices.framework CFStringRef extension = (__bridge CFStringRef)[path pathExtension]; CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL); assert(UTI != NULL); NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType)); assert(mimetype != NULL); CFRelease(UTI); return mimetype; } - (NSString *)generateBoundaryString { return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]]; }
그런 다음 요청을 제출하십시오. 여기에는 많은 옵션이 있습니다.
예를 들어를 사용하는
NSURLSession
경우 다음을 만들 수 있습니다NSURLSessionUploadTask
.NSURLSession *session = [NSURLSession sharedSession]; // use sharedSession or create your own NSURLSessionTask *task = [session uploadTaskWithRequest:request fromData:httpBody completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"error = %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"result = %@", result); }]; [task resume];
또는 다음을 만들 수 있습니다
NSURLSessionDataTask
.request.HTTPBody = httpBody; NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"error = %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"result = %@", result); }]; [task resume];
위의 내용은 서버가 텍스트 응답 만 반환한다고 가정합니다. 서버가 JSON을 반환하는 것이 더 낫습니다.이 경우 method
NSJSONSerialization
대신 사용하는 것이 좋습니다 .NSString
initWithData
마찬가지로
NSURLSession
위 의 완료 블록 변환 을 사용하고 있지만 더 풍부한 델리게이트 기반 변환도 자유롭게 사용하십시오. 그러나 그것은이 질문의 범위를 벗어난 것처럼 보이므로 여러분에게 맡기겠습니다.
그러나 이것은 아이디어를 잘 보여줍니다.
위의 것보다 훨씬 쉽게 AFNetworking 을 사용하여 위의 1 단계와 2 단계를 반복하고 다음을 호출 할 수 있다는 점을 지적하지 않았다면 실망 할 것입니다 .
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON; if web service returns JSON, remove this line
NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSError *error;
if (![formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"avatar" fileName:[path lastPathComponent] mimeType:@"image/png" error:&error]) {
NSLog(@"error appending part: %@", error);
}
} progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(@"responseObject = %@", responseObject);
} failure:^(NSURLSessionTask *task, NSError *error) {
NSLog(@"error = %@", error);
}];
if (!task) {
NSLog(@"Creation of task failed.");
}
Objective-C와 함께 멀티 파트 또는 양식 데이터를 사용하여 여러 이미지 게시
-(void)multipleimageandstring
{
NSString *urlString=@"URL NAME";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
NSMutableData *body = [NSMutableData data];
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request addValue:contentType forHTTPHeaderField:@"Content-Type"];
// file
float low_bound = 0;
float high_bound =5000;
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);//image1
int intRndValue = (int)(rndValue + 0.5);
NSString *str_image1 = [@(intRndValue) stringValue];
UIImage *chosenImage1=[UIImage imageNamed:@"Purchase_GUI_curves-12 copy.png"];
NSData *imageData = UIImageJPEGRepresentation(chosenImage1, 90);
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"files\"; filename=\"%@.png\"\r\n",str_image1] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"name\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Nilesh" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"apipassword\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:app.password] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"adminId\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:app.adminId] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// close form
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// set request body
[request setHTTPBody:body];
//return and test
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(@"%@", returnString);
}
MIME 유형이 다른 비디오 및 이미지 데이터 모두에 이것을 사용하십시오.
NSDictionary *param;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// 1. Create `AFHTTPRequestSerializer` which will create your request.
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSMutableURLRequest *request;
NSData *fileData;
if ([objDoc.url containsString:@".mp4"]) {
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"application/json"];
[serializer setValue:@"video/mp4" forHTTPHeaderField:@"Content-Type"];
manager.requestSerializer = serializer;
}
// 2. Create an `NSMutableURLRequest`.
NSLog(@"filename =%@",objDoc.url);
request= [serializer multipartFormRequestWithMethod:@"POST" URLString:strUrl parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
if ([objDoc.url containsString:@".mp4"]) {
[formData appendPartWithFileData:fileData
name:@"File"
fileName:@"video.mp4"
mimeType:@"video/mp4"];
}else{
[formData appendPartWithFileData:fileData
name:@"File"
fileName:@"image.jpeg"
mimeType:@"image/jpeg"];
}
} error:nil];
// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.
self.objeDocument.isUploading = [NSNumber numberWithInt:1];
self.operation = [manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error!" message:@"The document attached has failed to upload." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
[self.operation cancel];
NSLog(@"Failure %@", error.description);
}];
// 4. Set the progress block of the operation.
[self.operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
long long totalBytesWritten,
long long totalBytesExpectedToWrite) {
NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
}];
// 5. Begin!
[self.operation start];
여러 이미지 또는 다른 파일 형식을 업로드하려는 경우 잠시 동안이 문제로 고생했습니다. 다음을 사용하여 다음을 수행 할 수 있습니다. AFNetworking 3.0
NSDictionary *params = @{key : value,
..... etc
};
NSString *urlString = @"http://..... your endpoint url";
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON;
NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
for (int x = 0 ; x< contentArray.count; x++) {
AttachmentsModel *model = contentArray[x];
if(model.type == ImageAttachmentType){
[formData appendPartWithFileData:model.data name:model.name fileName:model.fileName mimeType:model.mimeType];
}else if(model.type == AudioAttachmentType){
NSURL *urlVideoFile = [NSURL fileURLWithPath:model.path];
[formData appendPartWithFileURL:urlVideoFile name:model.name fileName:model.fileName mimeType:model.mimeType error:nil];
}else{
[formData appendPartWithFileURL:model.url name:model.name fileName:model.fileName mimeType:model.mimeType error:nil];
}
}
} progress:nil success:^(NSURLSessionTask *task, id responseObject) {
[Utility stopLoading];
NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(@"result = %@", result);
id json = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
if (block) {
//your response comes here
}
} failure:^(NSURLSessionTask *task, NSError *error) {
NSLog(@"error = %@", error);
}];
if (!task) {
NSLog(@"Creation of task failed.");
}
내 AttachmentsModel의 모습은 다음과 같습니다.
// AttachmentsModel.h
typedef enum AttachmnetType{
ImageAttachmentType,
AudioAttachmentType,
VideoAttachmentType
} AttachmnetType;
@interface AttachmentsModel : NSObject
@property (strong, nonatomic) NSString *path;
@property (strong, nonatomic) NSData *data;
@property (strong, nonatomic) NSString *mimeType;
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *fileName;
@property (strong, nonatomic) NSURL *url;
이 시도:
스위프트 5
private func buildMultipartDataRequest(_ request: NetworkRequest, baseURL: NetworkEndPoint) -> URLRequest? {
var returnRequest: URLRequest?
if let data = request.multipartData,
let mimeType = request.mimeType,
let fileName = request.fileName {
var requestPath = request.endPoint.value
if let urlParameters = request.urlParameters {
requestPath += urlParameters.requestString()
}
let completePath = String(format: "%@%@", baseURL.value, requestPath)
if let cleanPath = completePath.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
let url = URL(string: cleanPath) {
returnRequest = URLRequest(url: url)
returnRequest?.httpMethod = request.HTTPMethod.rawValue
var allheaders: [String: String] = [ :]
if let headers = request.headers {
allheaders = headers
}
returnRequest?.allHTTPHeaderFields = allheaders
let boundary = boundaryString()
returnRequest?.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let encoding: UInt = String.Encoding.utf8.rawValue
if let boundaryStartData = "--\(boundary)\r\n".data(using: String.Encoding(rawValue: encoding)),
let fileNameData = "Content-Disposition:form-data; name=\"picture\"; filename=\"\(fileName)\"\r\n".data(using: String.Encoding(rawValue: encoding)),
let contentTypeData = "Content-Type: \(mimeType)\r\n\r\n".data(using: String.Encoding(rawValue: encoding)),
let endLineData = "\r\n".data(using: String.Encoding(rawValue: encoding)),
let boundaryEndData = "--\(boundary)--\r\n".data(using: String.Encoding(rawValue: encoding)) {
var body = Data()
if let bodyParameters = request.bodyParameters as? [String: AnyObject] {
bodyParameters.forEach { (pair) in
if let key = "Content-Disposition: form-data; name=\"\(pair.key)\"\r\n\r\n".data(using: String.Encoding(rawValue: encoding)),
let value = "\(pair.value)\r\n".data(using: String.Encoding(rawValue: encoding)) {
body.append(boundaryStartData)
body.append(key)
body.append(value)
}
}
}
body.append(boundaryStartData)
body.append(fileNameData)
body.append(contentTypeData)
body.append(data)
body.append(endLineData)
body.append(boundaryEndData)
returnRequest?.httpBody = body as Data
}
}
}
return returnRequest as URLRequest?
}
어디에 NetworkRequest
-요청 정보를 캡슐화하는 간단한 프로토콜
protocol NetworkRequest: class {
var HTTPMethod: NetworkRequestType { get }
var endPoint: NetworkEndPoint { get }
var urlParameters: [String: AnyObject]? { get }
var bodyParameters: AnyObject? { get }
var headers: [String: String]? { get }
var multipartData: Data? { get }
var mimeType: NetworkMimeType? { get }
var fileName: String? { get }
}
NetworkEndPoint
-endPoint 값
struct NetworkEndPoint {
let value: String
}
경계 스팅
private func boundaryString() -> String {
return "Boundary-\(UUID().uuidString)"
}
NetworkRequestType
:
enum NetworkRequestType: String {
case UNKNOWN
case POST
case GET
case PUT
case DELETE
case PATCH
// ....
}
NetworkMimeType
enum NetworkMimeType: String {
case html, htm, shtml = "text/html"
case css = "text/css"
case xml = "text/xml"
case gif = "image/gif"
case jpeg, jpg = "image/jpeg"
case jScript = "application/javascript"
case atom = "application/atom+xml"
case rss = "application/rss+xml"
case mml = "text/mathml"
case txt = "text/plain"
case jad = "text/vnd.sun.j2me.app-descriptor"
case wml = "text/vnd.wap.wml"
case htc = "text/x-component"
case png = "image/png"
case tiff, tif = "image/tiff"
case wbmp = "image/vnd.wap.wbmp"
case ico = "image/x-icon"
case jng = "image/x-jng"
case bmp = "image/x-ms-bmp"
case svg, svgz = "image/svg+xml"
case webp = "image/webp"
case woff = "application/font-woff"
case jar, war, ear = "application/java-archive"
case json = "application/json"
case hqx = "application/mac-binhex40"
case doc = "application/msword"
case pdf = "application/pdf"
case postscript, eps, aiPostscript = "application/postscript"
case rtf = "application/rtf"
case m3u8 = "application/vnd.apple.mpegurl"
case xls = "application/vnd.ms-excel"
case eot = "application/vnd.ms-fontobject"
case ppt = "application/vnd.ms-powerpoint"
case wmlc = "application/vnd.wap.wmlc"
case kml = "application/vnd.google-earth.kml+xml"
case kmz = "application/vnd.google-earth.kmz"
case sevenZ = "application/x-7z-compressed"
case cco = "application/x-cocoa"
case jardiff = "application/x-java-archive-diff"
case jnlp = "application/x-java-jnlp-file"
case run = "application/x-makeself"
case perl, perlm = "application/x-perl"
case prc, pdb = "application/x-pilot"
case rar = "application/x-rar-compressed"
case rpm = "application/x-redhat-package-manager"
case sea = "application/x-sea"
case swf = "application/x-shockwave-flash"
case sit = "application/x-stuffit"
case tcl = "application/x-tcl"
case der, pem, crt = "application/x-x509-ca-cert"
case xpi = "application/x-xpinstall"
case xhtml = "application/xhtml+xml"
case xspf = "application/xspf+xml"
case zip = "application/zip"
case bin, exe, dll, deb, dmg, iso, img, msi, msp, msm = "application/octet-stream"
case docx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
case xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
case pptx = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
case mid, midi, kar = "audio/midi"
case mp3 = "audio/mpeg"
case ogg = "audio/ogg"
case m4a = "audio/x-m4a"
case realAudio = "audio/x-realaudio"
case threegpp, threegp = "video/3gpp"
case mpts = "video/mp2t"
case mp4 = "video/mp4"
case mpeg, mpg = "video/mpeg"
case mov = "video/quicktime"
case webm = "video/webm"
case flv = "video/x-flv"
case m4v = "video/x-m4v"
case mng = "video/x-mng"
case asx, asf = "video/x-ms-asf"
case wmv = "video/x-ms-wmv"
case avi = "video/x-msvideo"
}
참고 URL : https://stackoverflow.com/questions/24250475/post-multipart-form-data-with-objective-c
'Program Tip' 카테고리의 다른 글
해시 할 해시 배열 (0) | 2020.11.29 |
---|---|
AngularJS 용 ui-router로 쿼리 매개 변수를 추출하는 방법은 무엇입니까? (0) | 2020.11.29 |
rspec으로 ActionMailer delivery_later를 테스트하는 방법 (0) | 2020.11.29 |
GUID는 정확히 무엇입니까? (0) | 2020.11.29 |
Java의 void 메소드에서 return 키워드는 무엇을합니까? (0) | 2020.11.29 |