将图像作为 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");
    }
}

一些观察:

  1. 一个问题是请求中存在 --(boundary)-- 字符串。它应该只出现在请求的末尾。

  2. 第二个问题是您似乎是在每个部分的开头 结尾处编写此边界字符串。它应该在每个部分的开头出现一次。也就是说,它应该只在两个字段之间出现一次。

    最重要的是,--(boundary) 应该出现在请求的每个“部分”的开头,--(boundary)-- 字符串应该出现在结尾

  3. 您已将上传文件的 Content-Type 注释掉。我不确定您为什么这样做(如果它不是 JPG,请将该内容类型替换为适当的内容类型),但在此过程中,您删除了应该出现在该部分 [ 之后的 \r\n\r\n =46=] 和数据之前。您现在不仅缺少 Content-Type,还缺少 \r\n

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

坦率地说,您可能会考虑放弃此创建您自己的多部分请求的代码,并使用已建立的库,如 AFNetworking,它可以正确地执行此操作。没有必要 re-invent 方向盘。