2016-08-11 5 views
15

Używam NSMutableURLRequest do wysyłania danych POST do skryptu PHP po stronie serwera, który wysyła e-maile za pomocą SendGrid. Działa to dobrze. Jednak nie mam pojęcia, jak poprawnie ułożyć UIImagedata, aby wysłać jako załącznik. Oto mój obecny kod:Jak wysłać załącznik ze zdjęciami e-mail w systemie iOS za pomocą żądania POST do SendGrid?

// Choose an image from your photo library 
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 
    chosenImage = info[UIImagePickerControllerEditedImage]; // chosenImage = UIImage 
    pickedData = UIImagePNGRepresentation(chosenImage); // pickedData = NSData 
    attachment = TRUE; 
    [picker dismissViewControllerAnimated:YES completion:NULL]; 
} 

-(void)sendMail { 
    toEmailAddress = @"[email protected]"; 
    subject = @"Some Subject"; 
    message = @"Some message..."; 
    fullName = @"Mister Bla Bla"; 

    if (attachment == TRUE) { 
     // Create NSData object as PNG image data from camera image 
     NSString *picAttachment = [NSString stringWithFormat:@"%lu",(unsigned long)[pickedData length]]; 
     NSString *picName = @"Photo"; 
     post = [NSString stringWithFormat:@"&toEmailAddress=%@&subject=%@&message=%@&fullName=%@&picAttachment=%@&picName=%@", toEmailAddress, subject, message, fullName, picAttachment, picName]; 
    } else { 
     post = [NSString stringWithFormat:@"&toEmailAddress=%@&subject=%@&message=%@&fullName=%@", toEmailAddress, subject, message, fullName]; 
    } 

    NSData * postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO]; 
    NSString * postLength = [NSString stringWithFormat:@"%lu",(unsigned long)[postData length]]; 
    NSMutableURLRequest * request = [[[NSMutableURLRequest alloc] init] autorelease]; 
    [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.someURL.com/sendgrid.php"]]]; 
    [request setHTTPMethod:@"POST"]; 
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
    [request setHTTPBody:postData]; 

    // send the POST request, and read the reply by creating a new NSURLSession: 
    NSURLSession *conn = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; 
    [[conn dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
     NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
     NSLog(@"requestReply: %@", requestReply); // Return response from PHP script on server. 
    }] resume]; 
} 

W przypadku badania tego pytania może się okazać, że istnieje istniejąca libra SendGrid iOS. Niestety nie jest to odpowiedź. Ludzie z SendGrid mówią, żebym nie używał biblioteki z powodu obaw związanych z bezpieczeństwem.

+0

Wow, tak wiele przebojów i nikt nie wyjaśnia, że ​​mówisz o bezpośrednim użyciu SendGrid. Można zmienić 'skrypt PHP po stronie serwera, który wysyła wiadomości e-mail za pomocą SendGrid' do' SendGrid endpoint', ponieważ pierwszy dotyczy własnego serwera, a drugi dotyczy serwera SendGrid. W końcu możesz dodać komentarz do mojej odpowiedzi. Przy okazji dodałem wyjaśnienie i link do dokumentów opisujących, co należy zrobić, aby bezpośrednio przesłać plik. Mam nadzieję, że to pomoże. –

Odpowiedz

3

Nowa odpowiedź:

Aby przesłać plik jako e-mail przyłączenie bezpośrednio do SendGrid należy użyć Web API v3 i utworzyć żądanie, jak opisano w docs.

Przede wszystkim musisz podać add authentication header na żądanie. Po drugie, musisz przekonwertować swoje dane do formatu JSON. Jeżeli mówimy o plikach trzeba zakodować złożyć danych z Base64, jak opisano w body parameters section:

JSON PARAMETER: attachements/content 
TYPE: string 
REQUIRED: Yes 
The Base64 encoded content of the attachment. 

Również spojrzeć na disposition i content_id params: oni pomogą Ci skonfigurować swój wygląd pliku w Poczta.

Old odpowiedź:

Standardowy sposób przesyłania obu parametrów i plików używa żądania POST z multipart messages. Mam zmienić swój kod, aby utworzyć dane tego formatu:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 
    UIImage* image = info[UIImagePickerControllerEditedImage]; 
    NSDictionary* params = @{ 
    @"toEmailAddress" : @"[email protected]", 
    @"subject" : @"Some Subject", 
    @"message" : @"Some message...", 
    @"fullName" : @"Mister Bla Bla", 
    }; 
    [picker dismissViewControllerAnimated:YES completion:^{ 
    [self sendMailWithParams:params image:image]; 
    }]; 
} 

static NSStringEncoding const kEncoding = NSUTF8StringEncoding; 

- (void)sendMailWithParams:(NSDictionary*)params image:(UIImage*)image { 
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
    request.URL = [NSURL URLWithString:@"http://www.someURL.com/sendgrid.php"]; 
    request.HTTPMethod = @"POST"; 

    NSString *boundary = [NSUUID UUID].UUIDString; 

    // define POST request as multipart 
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; 
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; 

    // prepare boundary 
    NSString *middleBoundary = [NSString stringWithFormat:@"--%@\r\n", boundary]; 
    NSData *middleBoundaryData = [middleBoundary dataUsingEncoding:kEncoding]; 

    NSMutableData* body = [NSMutableData data]; 

    // append params 
    [params enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) { 
    [body appendData:middleBoundaryData]; 
    NSData* fieldData = [self dataForKey:key value:value]; 
    [body appendData:fieldData]; 
    }]; 

    // append image 
    if (image) { 
    [body appendData:middleBoundaryData]; 
    NSData* imageData = [self dataForImage:image imageName:@"photo.png"]; 
    [body appendData:imageData]; 
    } 

    // add last boundary 
    NSString* lastBoundary = [NSString stringWithFormat:@"--%@--\r\n", boundary]; 
    NSData* lastBoundaryData = [lastBoundary dataUsingEncoding:kEncoding]; 
    [body appendData:lastBoundaryData]; 

    // set body to request 
    request.HTTPBody = body; 

    // add length of body 
    NSString *length = [NSString stringWithFormat:@"%llu", (uint64_t)body.length]; 
    [request setValue:length forHTTPHeaderField:@"Content-Length"]; 

    // send request 
    NSURLSession* session = [NSURLSession sharedSession]; 
    NSURLSessionDataTask* task = [session dataTaskWithRequest:request 
              completionHandler:^(NSData *data, 
                   NSURLResponse *response, 
                   NSError *error) { 
    // handle as you want 
    }]; 
    [task resume]; 
} 

- (NSData*)dataForImage:(UIImage*)image imageName:(NSString*)imageName { 
    NSString* fieldDescription = [NSString stringWithFormat: 
     @"Content-Disposition: form-data; name=\"image\"; filename=\"%@\"\r\n" 
     @"Content-Type: image/png\r\n\r\n", imageName]; 

    NSMutableData *data = [NSMutableData data]; 
    [data appendData:[fieldDescription dataUsingEncoding:kEncoding]]; 

    NSData* imageData = UIImagePNGRepresentation(image); 
    [data appendData:imageData]; 

    NSString* newLine = @"\r\n"; 
    NSData* newLineData = [newLine dataUsingEncoding:kEncoding]; 
    [data appendData:newLineData]; 

    return data; 
} 

- (NSData*)dataForKey:(NSString*)key value:(NSString*)value { 
    NSString* fieldDescription = [NSString stringWithFormat: 
     @"Content-Disposition: form-data; name=\"%@\"\r\n\r\n" 
     @"%@\r\n", key, value]; 
    return [fieldDescription dataUsingEncoding:kEncoding]; 
} 

Można użyć $_POST i $_FILES zmienne, aby uzyskać dostęp do danych załadowanych w skrypcie PHP. Aby uzyskać więcej informacji na temat wiadomości wieloczęściowych, zapoznaj się z dokumentami here.

+0

Dziękujemy za wejście Roman. Spróbuję wdrożyć twoją metodologię. – Marsman

Powiązane problemy