읽어 주셔서 감사합니다.
iOS를 처음 사용 multi-part form encoding
하고 iOS에서 사용하여 이미지와 텍스트를 업로드하려고합니다 .
curl
해당하는이 같은 것입니다 :curl -F "param1=value1" -F "param2=@testimage.jpg" "http://some.ip.address:5000/upload"
curl
위 의 명령은 예상되는 올바른 응답을 반환합니다.JSON.
문제점 :
HTTP 400 요청이 계속 수신됩니다. 이는 HTTP POST 본문을 작성하는 동안 뭔가 잘못되었음을 의미합니다.
내가 한 일 :
참고로 Flickr API iOS 앱 “POST 크기가 너무 큽니다!” 및 목표 C : 어떻게 HTTP POST를 사용하여 이미지와 텍스트를 업로드? . 하지만 계속 HTTP 400을받습니다.
나는 시도 ASIHttpRequest
했지만 거기에 다른 문제가있었습니다 (콜백이 호출되지 않았습니다). 그러나 개발자가 라이브러리 지원을 중단했다고 들었으므로 더 이상 조사하지 않았습니다. http://allseeing-i.com/[request_release] ;
누군가 나를 도울 수 있습니까?
답변
다음은 웹 서버에 이미지를 게시하는 내 앱의 코드입니다.
// Dictionary that holds post parameters. You can set your post parameters that your server accepts or programmed to accept.
NSMutableDictionary* _params = [[NSMutableDictionary alloc] init];
[_params setObject:[NSString stringWithString:@"1.0"] forKey:[NSString stringWithString:@"ver"]];
[_params setObject:[NSString stringWithString:@"en"] forKey:[NSString stringWithString:@"lan"]];
[_params setObject:[NSString stringWithFormat:@"%d", userId] forKey:[NSString stringWithString:@"userId"]];
[_params setObject:[NSString stringWithFormat:@"%@",title] forKey:[NSString stringWithString:@"title"]];
// the boundary string : a random string, that will not repeat in post data, to separate post data fields.
NSString *BoundaryConstant = [NSString stringWithString:@"----------V2ymHFg03ehbqgZCaKO6jy"];
// string constant for the post parameter 'file'. My server uses this name: `file`. Your's may differ
NSString* FileParamConstant = [NSString stringWithString:@"file"];
// the server url to which the image (or the media) is uploaded. Use your server url here
NSURL* requestURL = [NSURL URLWithString:@""];
// create request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];
// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", BoundaryConstant];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// post body
NSMutableData *body = [NSMutableData data];
// add params (all params are strings)
for (NSString *param in _params) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", [_params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
// add image data
NSData *imageData = UIImageJPEGRepresentation(imageToPost, 1.0);
if (imageData) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.jpg\"\r\n", FileParamConstant] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"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]];
// setting the body of the post to the reqeust
[request setHTTPBody:body];
// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%lu",(unsigned long) [body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
// set URL
[request setURL:requestURL];
답변
XJones 의 대답은 매력적이었습니다.
그러나 그는 언급 / 선언 된 변수하지 않았다 _params
, BoundaryConstant
그리고 requestURL
. 그래서 나는 그 부분을 그의 게시물에 추가 기능으로 게시하여 나중에 다른 사람들에게 도움이 될 수 있다고 생각했습니다.
// Dictionary that holds post parameters. You can set your post parameters that your server accepts or programmed to accept.
NSMutableDictionary* _params = [[NSMutableDictionary alloc] init];
[_params setObject:[NSString stringWithString:@"1.0"] forKey:[NSString stringWithString:@"ver"]];
[_params setObject:[NSString stringWithString:@"en"] forKey:[NSString stringWithString:@"lan"]];
[_params setObject:[NSString stringWithFormat:@"%d", userId] forKey:[NSString stringWithString:@"userId"]];
[_params setObject:[NSString stringWithFormat:@"%@",title] forKey:[NSString stringWithString:@"title"]];
// the boundary string : a random string, that will not repeat in post data, to separate post data fields.
NSString *BoundaryConstant = [NSString stringWithString:@"----------V2ymHFg03ehbqgZCaKO6jy"];
// string constant for the post parameter 'file'. My server uses this name: `file`. Your's may differ
NSString* FileParamConstant = [NSString stringWithString:@"file"];
// the server url to which the image (or the media) is uploaded. Use your server url here
NSURL* requestURL = [NSURL URLWithString:@""];
앞서 언급했듯이 이것은 그 자체로 대답이 아니라 XJones의 게시물에 대한 추가 기능 입니다.
답변
들어 HTTP 를 통해 전송 후 이미지와 사용자 이름과 암호를 게시하는 방법
NSString *str=[NSString stringWithFormat:@"%@registration.php",appdel.baseUrl];
NSString *urlString = [NSString stringWithFormat:@"%@",str];
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"];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"a.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imgData]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// parameter username
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"username\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[userName.text dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// parameter token
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"email\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[eMail.text dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// parameter method
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"pass\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[passWord.text dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
//parameter method
NSLog(@"%@",countryCode);
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"country\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[countryCode dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// close form
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[request setHTTPBody:body];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableLeaves error:nil];
Nslog(@"%@",dict);
//
답변
AFNetworking을 사용하십시오. 매개 변수 사전에 다른 매개 변수를 넣고 양식 데이터에 이미지 데이터를 추가하십시오.
//Upload Image Using AFNetworking
-(BOOL)uploadImageAFNetworkingWithURL:(NSString *)path andImage:(UIImage *)image andImageNameWithExtension:(NSString *)strImageName andParamDict:(NSDictionary *)dictParam andKeyForUploadingImage:(NSString *)keyUplaodImg{
NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
NSString *strError = EMPTY_STRING;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager POST:path parameters:dictParam constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:keyUplaodImg fileName:strImageName mimeType:@"image/jpeg"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"success = %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"error = %@", error);
NSLog(@"Response = %@", operation);
[strError stringByAppendingString:STR_ERR_MESSAGE];
}];
if(strError.length>0){
return NO;
}else{
return YES;
}
}
답변
다음은 파일을 멀티 파트 형식으로 업로드하기위한 유사한 네트워크 키트 라이브러리 입니다.
WebRequest *request = [[WebRequest alloc] initWithPath:@"...documents/create.json"];
// optional attributes
request.delegate = delegate;
request.notificationName = @"NotificationDocumentUploaded";
request.queue = myQueue;
NSMutableData *body = [NSMutableData data];
NSString *boundary = @"TeslaSchoolProjectFormBoundary";
[body appendPartName:@"document[name]" value:@"Test" boundary:boundary];
[body appendPartName:@"document[description]" value:@"This is a description" boundary:boundary];
[body appendPartName:@"document[category]" value:@"Drama" boundary:boundary];
...
[body appendPartName:@"commit" value:@"Save" boundary:boundary];
NSData *fileData = [[NSData alloc] initWithContentsOfURL:someFileURL];
[body appendPartFile:fileName name:@"document[file]" data:fileData mimeType:mimeType boundary:boundary];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
NSString *bodyLength = [NSString stringWithFormat:@"%lu",(unsigned long)[body length]];
[request addValue:bodyLength forHTTPHeaderField:@"Content-Length"];
[request setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];
// optional values
[request addValue:@"gzip,deflate,sdch" forHTTPHeaderField:@"Accept-Encoding"];
[request addValue:@"max-age=0" forHTTPHeaderField:@"Cache-Control"];
[request addValue:@"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" forHTTPHeaderField:@"Accept"];
[request addValue:@"en-US,en;q=0.8,hr;q=0.6,it;q=0.4,sk;q=0.2,sl;q=0.2,sr;q=0.2" forHTTPHeaderField:@"Accept-Language"];
[request setHTTPMethod:@"POST"];
[WebRequestProcessor process:request];
업로드 진행 상황을 알리 려면 위임 을 사용하십시오 .
요청이 완료되었을 때 알림 을 받으려면 notificationName 을 사용하십시오 .
이 요청을 작업 대기열 에 추가 하는 데 대기열 을 사용하면 적시에 처리됩니다.
답변
여기 @xjones가 제공 한 코드에서 번역 된 작동하는 신속한 코드가 있습니다. 도와 주셔서 감사합니다. 당신의 것이 나를 위해 일한 유일한 방법이었습니다. 이 방법을 사용하여 asp.net에서 만든 웹 서비스에 1 개의 이미지와 다른 매개 변수를 전송했습니다.
let params = NSMutableDictionary()
let boundaryConstant = "----------V2y2HFg03eptjbaKO0j1"
let file1ParamConstant = "file1"
params.setObject(device_id!, forKey: "deviceID")
let requestUrl = NSURL(string: "\(siteurl):\(port)/FileUpload/Upload")
let request = NSMutableURLRequest()
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
request.HTTPShouldHandleCookies=false
request.timeoutInterval = 30
request.HTTPMethod = "POST"
let contentType = "multipart/form-data; boundary=\(boundaryConstant)"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
let body = NSMutableData()
// parameters
for param in params {
body.appendData("--\(boundaryConstant)\r\n" .dataUsingEncoding(NSUTF8StringEncoding)! )
body.appendData("Content-Disposition: form-data; name=\"\(param)\"\r\n\r\n" .dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("\(param.value)\r\n" .dataUsingEncoding(NSUTF8StringEncoding)!)
}
// images
// image begin
body.appendData("--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"\(file1ParamConstant)\"; filename=\"image.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(passportImageData)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
// image end
body.appendData("--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
request.HTTPBody = body
let postLength = "\(body.length)"
request.setValue(postLength, forHTTPHeaderField: "Content-Length")
request.URL = requestUrl
var serverResponse = NSString()
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil
{
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString!)")
serverResponse = responseString!
}
task.resume()
답변
다음은 Swift 버전입니다. 양식 데이터를 보내지 않으려면 빈 양식 경계를 보내는 것이 여전히 중요합니다. 특히 Flask는 양식 데이터와 파일 데이터를 예상 request.files
하며 첫 번째 경계 없이는 채워 지지 않습니다 .
let composedData = NSMutableData()
// Set content type header
let BoundaryConstant = "--------------------------3d74a90a3bfb8696"
let contentType = "multipart/form-data; boundary=\(BoundaryConstant)"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
// Empty form boundary
composedData.appendData("--\(BoundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
// Build multipart form to send image
composedData.appendData("--\(BoundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
composedData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"image.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
composedData.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
composedData.appendData(rawData!)
composedData.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
composedData.appendData("--\(BoundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
request.HTTPBody = composedData
// Get content length
let length = "\(composedData.length)"
request.setValue(length, forHTTPHeaderField: "Content-Length")