将图像作为 ios 中的多部分文件上传到服务器 7
Upload image to server as multipart file in ios 7
在我的 ios 7 应用程序中,我试图将图像及其属性上传到我的服务器。我想传递 4 个值 x、y、w、h,其中 w 和 h 是宽度和高度,x 和 y 是 0。我通过分段文件上传使用图像上传的确切格式。但是我的服务器显示 "bad Input" 错误。我花了两天时间解决同一个问题并尝试了很多 things.But 他们没有工作。我正在按照下面给出的工作 android 代码进行操作。我还附上了我的 ios 7 代码。
有人请指出我的代码有什么问题或遗漏了什么。感谢您的回复。
Android代码:
public class OWBImageUpload implements Runnable{
URL connectURL;
String responseString;
String Title;
String Description;
byte[ ] dataToServer;
FileInputStream fileInputStream = null;
String urlString = "https://stage.oneworkbook.com/owb/attachments/photos";
String token = "";
public OWBImageUpload(String t, String vTitle, String vDesc){
try{
token = t;
connectURL = new URL(urlString);
Title= vTitle;
Description = vDesc;
}catch(Exception ex){
Log.i("HttpFileUpload","URL Malformatted");
}
}
public void uploadPhoto(FileInputStream fStream){
fileInputStream = fStream;
upload();
}
public void upload(){
String iFileName = Title;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
String Tag="fSnd";
try
{
Log.e(Tag,"Starting Http File Sending to URL");
// Open a HTTP connection to the URL
HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
conn.setRequestProperty(OWBConstants.OWB_TOKEN_AUTH, token);
conn.setRequestProperty(OWBConstants.CLIENT_ID, OWBConstants.ANDROID_CLIENT_ID);
conn.setRequestProperty(OWBConstants.CLIENT_SECRET, OWBConstants.ANDROID_CLIENT_SECRET);
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"x\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("0");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"y\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("0");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"w\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("1400");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"h\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("1400");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + iFileName +"\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[ ] buffer = new byte[bufferSize];
// read file and write it into form...
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable,maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0,bufferSize);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// close streams
fileInputStream.close();
dos.flush();
Log.e(Tag,"File Sent, Response: "+String.valueOf(conn.getResponseCode()));
InputStream is = conn.getInputStream();
// retrieve the response from server
int ch;
StringBuffer b =new StringBuffer();
while( ( ch = is.read() ) != -1 ){ b.append( (char)ch ); }
String s=b.toString();
Log.i("Response",s);
dos.close();
}
catch (MalformedURLException ex)
{
Log.e(Tag, "URL error: " + ex.getMessage(), ex);
}
catch (IOException ioe)
{
Log.e(Tag, "IO error: " + ioe.getMessage(), ioe);
}
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
我的 ios 7 代码:
- (void)postUserImage:(NSString *)url postData:(NSMutableDictionary *)imageDetails token:(NSString *)token onSuccess:(HttpRequestSuccess)completion onFailure:(HttpRequestFailure)failure {
self.httpURL = url;
self.httpSuccess = completion;
self.httpFailure = failure;
NSString *filePath = [imageDetails valueForKey:@"filePath"];
NSString *fileName = [imageDetails valueForKey:@"fileName"];
NSData *imageData;
if ([[NSFileManager defaultManager]fileExistsAtPath:filePath]) {
NSLog(@"file path exists");
imageData=[NSData dataWithContentsOfFile:filePath];
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
if(token != nil) {
[request setValue:token forHTTPHeaderField:@"x-owb-token"];
}
[request setValue:IOS_CLIENT_ID forHTTPHeaderField:CLIENT_ID];
[request setValue:IOS_CLIENT_SECRET forHTTPHeaderField:CLIENT_SECRET];
//[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
NSString *boundary = @"**********";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
NSMutableData *body = [[NSMutableData alloc]init];
// giving x,y,w,h
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"x\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *x=@"0";
[body appendData:[x dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"y\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *y=@"0";
[body appendData:[y dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"w\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *w=@"500";
[body appendData:[w dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"h\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *h=@"500";
[body appendData:[h dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// adding Image content
if (imageData) {
//[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] 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", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
}
[request setHTTPBody:body];
//NSLog(@"http request body:%@",body);
//[request setAllHTTPHeaderFields:[request allHTTPHeaderFields]];
//NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
//[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(connection == nil){
NSLog(@"BAD CONNECTION");
}
}
一些观察:
一个问题是请求中存在 --(boundary)--
字符串。它应该只出现在请求的末尾。
第二个问题是您似乎是在每个部分的开头 和 结尾处编写此边界字符串。它应该在每个部分的开头出现一次。也就是说,它应该只在两个字段之间出现一次。
最重要的是,--(boundary)
应该出现在请求的每个“部分”的开头,--(boundary)--
字符串应该出现在结尾
您已将上传文件的 Content-Type
注释掉。我不确定您为什么这样做(如果它不是 JPG,请将该内容类型替换为适当的内容类型),但在此过程中,您删除了应该出现在该部分 [ 之后的 \r\n\r\n
=46=] 和数据之前。您现在不仅缺少 Content-Type
,还缺少 \r\n
。
我建议您使用 Charles 之类的工具观察此请求,并将其与 well-formed 请求(例如来自您的 Android 代码)进行比较并进行比较。您应该验证这两个请求看起来是否相同。空行、出现的边界和 --
字符串非常重要。
坦率地说,您可能会考虑放弃此创建您自己的多部分请求的代码,并使用已建立的库,如 AFNetworking,它可以正确地执行此操作。没有必要 re-invent 方向盘。
在我的 ios 7 应用程序中,我试图将图像及其属性上传到我的服务器。我想传递 4 个值 x、y、w、h,其中 w 和 h 是宽度和高度,x 和 y 是 0。我通过分段文件上传使用图像上传的确切格式。但是我的服务器显示 "bad Input" 错误。我花了两天时间解决同一个问题并尝试了很多 things.But 他们没有工作。我正在按照下面给出的工作 android 代码进行操作。我还附上了我的 ios 7 代码。
有人请指出我的代码有什么问题或遗漏了什么。感谢您的回复。
Android代码:
public class OWBImageUpload implements Runnable{
URL connectURL;
String responseString;
String Title;
String Description;
byte[ ] dataToServer;
FileInputStream fileInputStream = null;
String urlString = "https://stage.oneworkbook.com/owb/attachments/photos";
String token = "";
public OWBImageUpload(String t, String vTitle, String vDesc){
try{
token = t;
connectURL = new URL(urlString);
Title= vTitle;
Description = vDesc;
}catch(Exception ex){
Log.i("HttpFileUpload","URL Malformatted");
}
}
public void uploadPhoto(FileInputStream fStream){
fileInputStream = fStream;
upload();
}
public void upload(){
String iFileName = Title;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
String Tag="fSnd";
try
{
Log.e(Tag,"Starting Http File Sending to URL");
// Open a HTTP connection to the URL
HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
conn.setRequestProperty(OWBConstants.OWB_TOKEN_AUTH, token);
conn.setRequestProperty(OWBConstants.CLIENT_ID, OWBConstants.ANDROID_CLIENT_ID);
conn.setRequestProperty(OWBConstants.CLIENT_SECRET, OWBConstants.ANDROID_CLIENT_SECRET);
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"x\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("0");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"y\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("0");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"w\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("1400");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"h\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes("1400");
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + iFileName +"\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[ ] buffer = new byte[bufferSize];
// read file and write it into form...
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable,maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0,bufferSize);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// close streams
fileInputStream.close();
dos.flush();
Log.e(Tag,"File Sent, Response: "+String.valueOf(conn.getResponseCode()));
InputStream is = conn.getInputStream();
// retrieve the response from server
int ch;
StringBuffer b =new StringBuffer();
while( ( ch = is.read() ) != -1 ){ b.append( (char)ch ); }
String s=b.toString();
Log.i("Response",s);
dos.close();
}
catch (MalformedURLException ex)
{
Log.e(Tag, "URL error: " + ex.getMessage(), ex);
}
catch (IOException ioe)
{
Log.e(Tag, "IO error: " + ioe.getMessage(), ioe);
}
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
我的 ios 7 代码:
- (void)postUserImage:(NSString *)url postData:(NSMutableDictionary *)imageDetails token:(NSString *)token onSuccess:(HttpRequestSuccess)completion onFailure:(HttpRequestFailure)failure {
self.httpURL = url;
self.httpSuccess = completion;
self.httpFailure = failure;
NSString *filePath = [imageDetails valueForKey:@"filePath"];
NSString *fileName = [imageDetails valueForKey:@"fileName"];
NSData *imageData;
if ([[NSFileManager defaultManager]fileExistsAtPath:filePath]) {
NSLog(@"file path exists");
imageData=[NSData dataWithContentsOfFile:filePath];
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
if(token != nil) {
[request setValue:token forHTTPHeaderField:@"x-owb-token"];
}
[request setValue:IOS_CLIENT_ID forHTTPHeaderField:CLIENT_ID];
[request setValue:IOS_CLIENT_SECRET forHTTPHeaderField:CLIENT_SECRET];
//[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
NSString *boundary = @"**********";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
NSMutableData *body = [[NSMutableData alloc]init];
// giving x,y,w,h
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"x\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *x=@"0";
[body appendData:[x dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"y\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *y=@"0";
[body appendData:[y dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"w\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *w=@"500";
[body appendData:[w dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"h\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *h=@"500";
[body appendData:[h dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// adding Image content
if (imageData) {
//[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] 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", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
}
[request setHTTPBody:body];
//NSLog(@"http request body:%@",body);
//[request setAllHTTPHeaderFields:[request allHTTPHeaderFields]];
//NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
//[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(connection == nil){
NSLog(@"BAD CONNECTION");
}
}
一些观察:
一个问题是请求中存在
--(boundary)--
字符串。它应该只出现在请求的末尾。第二个问题是您似乎是在每个部分的开头 和 结尾处编写此边界字符串。它应该在每个部分的开头出现一次。也就是说,它应该只在两个字段之间出现一次。
最重要的是,
--(boundary)
应该出现在请求的每个“部分”的开头,--(boundary)--
字符串应该出现在结尾您已将上传文件的
Content-Type
注释掉。我不确定您为什么这样做(如果它不是 JPG,请将该内容类型替换为适当的内容类型),但在此过程中,您删除了应该出现在该部分 [ 之后的\r\n\r\n
=46=] 和数据之前。您现在不仅缺少Content-Type
,还缺少\r\n
。
我建议您使用 Charles 之类的工具观察此请求,并将其与 well-formed 请求(例如来自您的 Android 代码)进行比较并进行比较。您应该验证这两个请求看起来是否相同。空行、出现的边界和 --
字符串非常重要。
坦率地说,您可能会考虑放弃此创建您自己的多部分请求的代码,并使用已建立的库,如 AFNetworking,它可以正确地执行此操作。没有必要 re-invent 方向盘。