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

时间:2015-01-29 12:01:02

标签: objective-c post ios7 nsurlconnection multipartform-data

在我的ios 7应用程序中,我尝试将带有属性的Image上传到我的服务器。我想传递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");
    }
}

1 个答案:

答案 0 :(得分:0)

有几点意见:

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

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

    底线,--(boundary)应出现在每个"部分"的开头。请求和--(boundary)--字符串应出现在最后

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

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

    坦率地说,您可以考虑放弃创建自己的多部分请求的代码,并使用已建立的库,如AFNetworking,它可以正确执行此操作。没有必要重新发明轮子。