Objective c 在ios 7中将图像作为多部分文件上载到服务器

Objective c 在ios 7中将图像作为多部分文件上载到服务器,objective-c,post,ios7,nsurlconnection,multipartform-data,Objective C,Post,Ios7,Nsurlconnection,Multipartform Data,在我的ios 7应用程序中,我试图将带有其属性的图像上载到我的服务器。我想传递4个值x,y,w,h,其中w和h是宽度和高度,x和y是0。我通过多部分文件上传使用了图像上传的精确格式。但我的服务器显示“错误输入”错误。我花了两天时间研究同一个问题,尝试了很多方法,但都不奏效。我正在遵循下面给出的工作android代码。此外,我附加我的ios 7代码 有人请指出什么是错误的或我的代码中缺少什么。谢谢你的回复 Android代码: public class OWBImageUpload impleme

在我的ios 7应用程序中,我试图将带有其属性的图像上载到我的服务器。我想传递4个值x,y,w,h,其中w和h是宽度和高度,x和y是0。我通过多部分文件上传使用了图像上传的精确格式。但我的服务器显示“错误输入”错误。我花了两天时间研究同一个问题,尝试了很多方法,但都不奏效。我正在遵循下面给出的工作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");
    }
}

以下是几点观察:

  • 一个问题是请求中存在
    -(边界)-->
    字符串。它应该只出现在请求的末尾

  • 第二个问题是,您似乎在每个部分的开始和结束处写入此边界字符串。它应该在每个零件的开头出现一次。也就是说,它应该只在两个字段之间出现一次

    底线是,
    --(边界)
    应该出现在请求的每个“部分”的开头,而
    --(边界)
    字符串应该出现在请求的结尾

  • 您已注释掉上载文件的
    内容类型
    。我不确定您为什么这样做(如果不是JPG,请用适当的内容类型替换该内容类型),但在此过程中,您删除了应显示在部件标题之后和数据之前的
    \r\n\r\n
    。您现在不仅缺少
    内容类型
    ,而且还缺少
    \r\n

  • 我建议您使用类似的工具观察此请求,并将其与格式良好的请求(例如来自您的Android代码)进行比较。您应该验证这两个请求看起来是否相同。空行、边界引用和
    --
    字符串非常重要


    坦白地说,你可以考虑放弃这个代码来创建你自己的多部分请求,并使用一个已建立的库,比如AfDeNoad,这样做是正确的。无需重新发明车轮。

    请参阅“谢谢”的提示。我试过了。但现在它显示“内部服务器错误”。您的请求可能仍然格式不正确。我注意到,您在一个部分的末尾和下一个部分的开头写入边界字符串(因此在两个字段之间出现两次)。这个边界字符串应该在每个部分的开头出现一次,就这样。此外,在上载文件的地方,您不仅注释了
    内容类型
    ,还注释了必要的
    \r\n
    。谢谢您的注释。这很难找到。在我的回复中,我得到了一张空白的图片。有什么想法吗?@AugustinJose No,这要归结到web服务API应该返回什么、请求的精确格式等等。你没有向我们展示Android代码是如何解析响应的(更不用说响应应该是一个图像了……或者你说它在服务器端是空白的?)。再一次,我建议观察一个像Charles这样的成功交易,然后将其与此交易进行比较,并确定到底有什么不同。但是没有更多的细节,很难说。谢谢你的帮助。我发现图像内容有问题。这是因为我传递的w和h(宽度和高度)值非常少。我想在普通iPhone裁剪后传递精确的图像宽度和高度。有什么想法吗?我正在使用图像采集器从相机和多媒体资料中拍摄图像,并将其保存到documents\目录中,然后转换为NSData。