React native-отправка фото на почту

Я пытаюсь отправить недавно в app - captured фото по почте и сталкиваюсь со следующей ошибкой:

(для функциональности рассылки я использую этот модуль:var Mailer = require('NativeModules').RNMail;

Я пытаюсь отправить фотографию по почте с помощью этого модуля и получить следующую ошибку:

index.ios.bundle:28842Exception '-[MFMailComposeInternalViewController addAttachmentData:mimeType:fileName:] attachment must not be nil.' was thrown while invoking mail on target RNMail with params (
        {
        attachment =         {
            name = Ladunek;
            path = "assets-library://asset/asset.JPG?id=3B7DBB2E-1271-4D86-A5F2-A0CEEE7CC4DE&ext=JPG";
            type = jpg;
        };
        body = "body";
        isHTML = 1;
        recipients =         (
            "placeholder@mail.com"
        );
        subject = Ladunek;
    },
    9
)

это код вызова:

.then((data, path) => {
        console.log(data)
        console.log(data.path)
        Mailer.mail({
          subject: 'Ladunek',
          recipients: ['placeholder@mail.com'],
          body: 'body',
          isHTML: true, // iOS only, exclude if false
          attachment: {
            path: data.path,  // The absolute path of the file from which to read data.
            type: 'jpg',   // Mime Type: jpg, png, doc, ppt, html, pdf
            name: 'Ladunek',   // Optional: Custom filename for attachment
          }
        }, (error, event) => {
            if(error) {
              AlertIOS.alert('Error', 'Could not send mail. Please send a mail to support@example.com');
            }
        });
      })

- это неверный путь? Или это может быть что-то еще.

редактировать

Я получаю путь к файлу с помощью этого модуля react-native-camera вот так:

событие:

takePicture() {
    this.camera.capture()
      .then((data, path) =>

элемент:

<Camera
              ref={(cam) => {
                this.camera = cam;
              }}
              style={{
                    flex: 1,
                    justifyContent: 'flex-end',
                    alignItems: 'center',
                    height: 400,
                    width: Dimensions.get('window').width
                  }}
              aspect={Camera.constants.Aspect.fill}>
              <Text style={{
                        flex: 0,
                        backgroundColor: '#fff',
                        borderRadius: 5,
                        color: '#000',
                        padding: 10,
                        margin: 40
                      }} onPress={this.takePicture.bind(this)}>{cameraIcon}</Text>
            </Camera>

обновление 2

после, в том числе файл obj-c для преобразования uri в путь я получаю следующую ошибку:

ExceptionsManager.js:76 JSON value '<null>' of type NSNull cannot be converted to NSString

Я "удалил" неправильные строки из следующего кода? :/

файл Obj-c содержание:

#import "RCTBridgeModule.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <UIKit/UIKit.h>
@interface ReadImageData : NSObject <RCTBridgeModule>
@end

@implementation ReadImageData

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(readImage:(NSString *)input callback:(RCTResponseSenderBlock)callback)
{

  // Create NSURL from uri
  NSURL *url = [[NSURL alloc] initWithString:input];

  // Create an ALAssetsLibrary instance. This provides access to the
  // videos and photos that are under the control of the Photos application.
  //ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

  // Using the ALAssetsLibrary instance and our NSURL object open the image.
  //[library assetForURL:url resultBlock:^(ALAsset *asset) {

    // Create an ALAssetRepresentation object using our asset
    // and turn it into a bitmap using the CGImageRef opaque type.
    //CGImageRef imageRef = [asset thumbnail];

    // Create UIImageJPEGRepresentation from CGImageRef
   // NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.1);

    // Convert to base64 encoded string
    // NSString *base64Encoded = [imageData base64EncodedStringWithOptions:0];

    callback(@[url]);

  //} failureBlock:^(NSError *error) {
    //NSLog(@"that didn't work %@", error);
  //}];



}
@end

1 ответов


------ ОТРЕДАКТИРОВАННЫЙ ОТВЕТ НИЖЕ ------

Хорошо, Итак, у меня наконец-то есть Mac и я смог изучить эту проблему более подробно.

это то, что я нашел для Android и iOS.

предполагается, что вы используете реагировать родной камеры вместе с react-native-mail

- 1: Абсолютный Путь

добавить свойство captureTarget={Camera.constants.CaptureTarget.disk} to Camera компонент, как Итак:

<Camera
  captureTarget={Camera.constants.CaptureTarget.disk}
  ref={(cam) => {
    this.camera = cam;
  }}
  style={styles.preview}
  aspect={Camera.constants.Aspect.fill}>
  <Text style={styles.capture} onPress={this.takePicture.bind(this)}>[CAPTURE]</Text>
</Camera>

теперь компонент камеры должен возвратить абсолютное путь к файлу вместо uri.

и Android вы должны увидеть нечто вроде этого:

"file:///storage/emulated/0 / Pictures / RCTCameraModule / IMG_20160730_060652.формат JPG"

вместо:

"содержание: / / медиа / внешний/изображения / медиа / 86"

и iOS вы должны сделать что-то вроде этого:

"/Users/anton/Library/Developer/CoreSimulator/Devices/9A15F203-9A58-41C5-A4FC-EA25FAAE92BD/data/Containers/Data/Application/79FF93F9-BA89-4F4C-8809-277BEECD447D/Documents/EFFF0ECE-4063-4FE5-984E-E76506788350.формат JPG"

вместо:

"assets-library: / / актив / актив.В JPG?id=0058FA4A-268F-408A-9150-017A3DA368D2 & ext=JPG"

- 2: подводные камни

iOS:

если сбой MFMailComposeViewController от Apple, и вы видите следующее сообщение об ошибке:

enter image description here

Это скорее всего потому, что вы используете приложение на iOS 9 симулятор. Решение: либо протестируйте приложение на реальном устройстве или загрузите старый симулятор, такой как iOS 8.4.

более подробную информацию по этому вопросу можно найти здесь

Android:

на момент написания этой статьи нет крепления для Android.

устранение: (PR был сделан, чтобы добавить эту функцию, но если вы не можете ждать)

добавить следующий код в файл RNMAILModule.java

if (options.hasKey("attachment") && !options.isNull("attachment")) {
  i.putExtra(Intent.EXTRA_STREAM, Uri.parse(options.getMap("attachment").getString("path")));
}

когда как Android, так и iOS работают, у вас должно быть что-то вроде этого:

enter image description here enter image description here

и вот рабочий код:

var Mailer = require('NativeModules').RNMail;
import Camera from 'react-native-camera';

import React, {Component} from 'react';
import
{
  View,
  TouchableHighlight,
  Text,
  StyleSheet,
  Dimensions,
  CameraRoll
}
from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  preview: {
    flex: 1,
    justifyContent: 'flex-end',
    alignItems: 'center',
    height: Dimensions.get('window').height,
    width: Dimensions.get('window').width
  },
  capture: {
    flex: 0,
    backgroundColor: '#fff',
    borderRadius: 5,
    color: '#000',
    padding: 10,
    margin: 40
  }
});

class SendPhoto extends Component {
  takePicture() {
    this.camera.capture()
      .then((data) => {
        console.log(data.path)
        Mailer.mail({
          subject: 'Ladunek',
          recipients: ['placeholder@mail.com'],
          body: 'body',
          isHTML: true, // iOS only, exclude if false
          attachment: {
            path: data.path,  // The absolute path of the file from which to read data.
            type: 'jpg',   // Mime Type: jpg, png, doc, ppt, html, pdf
            name: 'Ladunek',   // Optional: Custom filename for attachment
          }
        }, (error, event) => {
            if(error) {
              AlertIOS.alert('Error', 'Could not send mail. Please send a mail to support@example.com');
            }
        })
      })
      .catch(err => console.error(err));
  }

  render() {
    return(
      <View>
        <View style={styles.container}>
          <Camera
            captureTarget={Camera.constants.CaptureTarget.disk}
            ref={(cam) => {
              this.camera = cam;
            }}
            style={styles.preview}
            aspect={Camera.constants.Aspect.fill}>
            <Text style={styles.capture} onPress={this.takePicture.bind(this)}>[CAPTURE]</Text>
          </Camera>
        </View>
      </View>
    );
  }
}
export default SendPhoto;

------ СТАРЫЙ ОТВЕТ НИЖЕ ------

Я никогда не использовал этот модуль раньше, но похоже, что он ожидает абсолютный путь к файлу, однако вы предоставляете файл uri.

как вы получаете этот файл uri?

попробуйте использовать react-native-get-real-path модуль, чтобы увидеть, если это поможет, вы можете найти его здесь:react-native-get-real-path

т. е. преобразуйте uri файла для получения реального пути и используйте его как путь