Search code examples
iosweb-services4d-database

Upload photo from iPhone to 4D Server


I am looking to upload a photo from iPhone to a 4D Server. Specifically to upload a photo taken on an iPhone, uploaded to a 4D Server and stored as a JPEG image in the WebFolder. I am using 4D Server version 12 and 13. I have looked at other postings here but I cannot make any of them apply to 4D. Anyone know how to do this?


Solution

  • It took me a while but I finally puzzled together the various procedures to make this work. Thumbs up to the iriphon blog (http://www.iriphon.com/2011/11/09/ios-uploading-an-image-from-your-iphone-to-a-server/) for putting me on the right track.

    Here is the iOS code I used:

    -(IBAction)uploadPhoto:(id)sender {
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.domain.com/4DACTION/showcaseUploadPic"]
                                                                cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                            timeoutInterval:60]; 
    
    [request setHTTPMethod:@"POST"]; 
    
    // We need to add a header field named Content-Type with a value that tells that it's a form and also add a boundary.
    // I just picked a boundary by using one from a previous trace, you can just copy/paste from the traces.
    NSString *boundary = @"----WebKitFormBoundaryQkZe6RUJZ2xbzXLB";
    
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
    
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"];
    // end of what we've added to the header.
    
    // the body of the post.
    NSMutableData *body = [NSMutableData data];
    
    // Now we need to append the different data 'segments'. We first start by adding the boundary.
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
    // Now append the image
    // Note that the name of the form field is exactly the same as in the trace ('picBLOB' in my case).
    // You can choose whatever filename you want.
    [body appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"picBLOB\" filename=\"image001.jpg\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    
    // We now need to tell the receiver what content type we have.
    // In my case it's a jpg image. If you have a png, set it to 'image/png'.
    [body appendData:[[NSString stringWithString:@"Content-Type: image/jpg\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    
    // Now we append the actual image data.
    // I use a NSData object called photoData.
    [body appendData:[NSData dataWithData:photoData]];
    
    NSLog(@"photoData size = %i",[photoData length]);
    
    // and again the delimiting boundary.
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
    // adding the body we've created to the request.
    [request setHTTPBody:body];
    
    NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    NSLog(@"connection = %@",connection);
    }
    

    Don't forget to include the NSURLConnection delegates!

    I used Wireshark, as described in the blog, to get the exact data I needed. I am using NSData to store the photo I had just taken with the camera and want to upload. Because of this my code is slightly different than if you wanted to upload a stored file.

    Here is the 4D (version 12) code:

    $ba:=BLOB size(picBLOB)
    C_PICTURE(imageVar)
    If (Undefined(picBLOB))  // in case user tries to reload /4DACTION/WEB_Set_Limits
    C_BLOB(picBLOB)
    End if 
    
    If (BLOB size(picBLOB)>0)  // did user select a file for uploading?
    C_STRING(255;$fileHeader)
    $offset:=0  // BLOB to text requires a variable for the offset parameter
    $fileHeader:=BLOB to text(picBLOB;Mac text without length;$offset;255)
    $fileNameBegin:=Position("filename=";$fileHeader)+10
    For ($i;$fileNameBegin;255)
    If ($fileHeader≤$i≥=Char(Double quote))
    $fileNameEnd:=$i
    $i:=255
    End if 
    End for 
    $fileName:=Substring($fileHeader;$fileNameBegin;$fileNameEnd-$fileNameBegin)
    $contentTypeBegin:=Position("Content-Type:";$fileHeader)+14
    For ($i;$contentTypeBegin;255)
    If ($fileHeader≤$i≥=Char(Carriage return))
    $contentTypeEnd:=$i
    $i:=255
    End if 
    End for 
    contentType:=Substring($fileHeader;$contentTypeBegin;$contentTypeEnd-$contentTypeBegin)
    DELETE FROM BLOB(picBLOB;0;$contentTypeEnd+3)
    
    BLOB TO PICTURE(picBLOB;imageVar;"JPEG")
    $FILENAME:=":WebFolder:myPhoto.jpg"
    WRITE PICTURE FILE($FILENAME;imageVar;"JPEG")
    
    End if 
    

    Here is the 4D (version 13) code:

    C_BLOB(picBLOB)
    C_PICTURE(imageVar)
    
    WEB GET BODY PART(1;picBLOB;myPhoto)
    
    If (BLOB size(picBLOB)>0)
    BLOB TO PICTURE(picBLOB;imageVar;"JPEG")
    $FILENAME:=":WebFolder:myPhoto.jpg"
    WRITE PICTURE FILE($FILENAME;imageVar;"JPEG")
    End if