问题描述
我正在尝试通过邮件发送最近在应用程序中拍摄的照片,但遇到以下错误:
(对于邮件功能,我正在使用此模块:var Mailer = require('NativeModules').RNMail;
我试图在此模块的帮助下通过邮件发送照片并收到以下错误:
index.ios.bundle:28842Exception '-[MFMailComposeInternalViewController addAttachmentData:mimeType:fileName:] 附件不能为零.'在使用参数调用目标 RNMail 上的邮件时被抛出({附件 = {名称 = 拉杜内克;path = "assets-library://asset/asset.JPG?id=3B7DBB2E-1271-4D86-A5F2-A0CEEE7CC4DE&ext=JPG";类型 = jpg;};身体 = "身体";isHTML = 1;收件人 = (占位符@mail.com");主题 = 拉杜尼克;},9)
这是调用代码:
.then((data, path) => {控制台日志(数据)控制台日志(数据路径)Mailer.mail({主题:'拉杜内克',收件人:['[email protected]'],身体:'身体',isHTML: true,//仅适用于 iOS,如果为 false 则排除附件: {path: data.path,//读取数据的文件的绝对路径.type: 'jpg',//Mime 类型:jpg、png、doc、ppt、html、pdfname: 'Ladunek',//可选:附件的自定义文件名}}, (错误, 事件) =>{如果(错误){AlertIOS.alert('Error', '无法发送邮件.请发送邮件至 [email protected]');}});})
路径是否无效?或者可能是别的什么.
编辑
我正在使用此模块获取文件路径 react-native-camera
像这样:
事件:
takePicture() {this.camera.capture().then((数据,路径) =>
元素:
{this.camera = cam;}}风格={{弹性:1,justifyContent: 'flex-end',alignItems: '中心',高度:400,宽度:Dimensions.get('window').width}}aspect={Camera.constants.Aspect.fill}><文字样式={{弹性:0,背景颜色:'#fff',边界半径:5,颜色:'#000',填充:10,保证金:40}} onPress={this.takePicture.bind(this)}>{cameraIcon}</Text></相机>
更新2
在包含
这很可能是因为您在 iOS 9 模拟器上运行该应用程序.解决方案:要么在真实设备上测试应用程序,要么下载较旧的模拟器,例如 iOS 8.4.
关于这个问题的更多信息可以在
这是工作代码:
var Mailer = require('NativeModules').RNMail;从'react-native-camera'导入相机;从反应"导入反应,{组件};进口{看法,可触摸突出显示,文本,样式表,方面,相机胶卷}来自反应原生";const 样式 = StyleSheet.create({容器: {弹性:1},预习: {弹性:1,justifyContent: 'flex-end',alignItems: '中心',高度:Dimensions.get('window').height,宽度:Dimensions.get('window').width},捕获: {弹性:0,背景颜色:'#fff',边界半径:5,颜色:'#000',填充:10,保证金:40}});类 SendPhoto 扩展组件 {拍照片() {this.camera.capture().then((数据) => {控制台日志(数据路径)Mailer.mail({主题:'拉杜内克',收件人:['[email protected]'],身体:'身体',isHTML: true,//仅适用于 iOS,如果为 false 则排除附件: {path: data.path,//读取数据的文件的绝对路径.type: 'jpg',//Mime 类型:jpg、png、doc、ppt、html、pdfname: 'Ladunek',//可选:附件的自定义文件名}}, (错误, 事件) =>{如果(错误){AlertIOS.alert('Error', '无法发送邮件.请发送邮件至 [email protected]');}})}).catch(err => console.error(err));}使成为() {返回(<视图样式={styles.container}><相机captureTarget={Camera.constants.CaptureTarget.disk}ref={(凸轮)=>{this.camera = cam;}}style={styles.preview}aspect={Camera.constants.Aspect.fill}><Text style={styles.capture} onPress={this.takePicture.bind(this)}>[CAPTURE]</Text></相机></查看></查看>);}}导出默认 SendPhoto;
------ 下面的旧答案------
我以前从未使用过这个模块,但看起来它需要文件的绝对路径,但是您提供的是文件 uri.
你是如何获得这个文件uri的?
尝试使用 react-native-get-real-path 模块看看是否有帮助,你可以在这里找到它:react-native-get-real-path
即将您的文件 uri 转换为实际路径,并将其用作 path
i am trying to send a recently in app - captured photo by mail and am encountering the following error:
(for the mailing functionality i am using this module : var Mailer = require('NativeModules').RNMail;
I am trying to send a photo by mail with the help of this module and get the following error:
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 = (
"[email protected]"
);
subject = Ladunek;
},
9
)
This is the invoking code :
.then((data, path) => {
console.log(data)
console.log(data.path)
Mailer.mail({
subject: 'Ladunek',
recipients: ['[email protected]'],
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 [email protected]');
}
});
})
Is the path invalid? Or might it be something else.
EDIT
I am obtaining the file path with this module react-native-camera
like so:
Event:
takePicture() {
this.camera.capture()
.then((data, path) =>
Element:
<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>
UPDATE2
After including an obj-c file for uri to path transformation I am receiving the following error now:
ExceptionsManager.js:76 JSON value '<null>' of type NSNull cannot be converted to NSString
Did I "remove" the wrong lines from the following code? :/
Obj-c File content:
#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
------ EDITED ANSWER BELOW ------
Okay, so I finally have a Mac and was able to look into this issue in more details.
This is what I found for both Android and iOS.
The assumption is that you are using react-native-camera together with react-native-mail
- 1: Absolute Path
Add property captureTarget={Camera.constants.CaptureTarget.disk}
to Camera
component like so:
<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>
Now camera component should return absolute file path instead of uri.
So for Android you should see something like this:
"file:///storage/emulated/0/Pictures/RCTCameraModule/IMG_20160730_060652.jpg"
instead of:
"content://media/external/images/media/86"
and for iOS you should get something like this:
"/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"
instead of:
"assets-library://asset/asset.JPG?id=0058FA4A-268F-408A-9150-017A3DA368D2&ext=JPG"
- 2: Pitfalls
iOS:
If Apple's MFMailComposeViewController crashes and you see the following error message:
This is most likely because you are running the app on iOS 9 Simulator. Solution: either test the app on real device, or download an older Simulator such as iOS 8.4.
More information on this issue can be found here
Android:
As of this writing there is no attachment support for Android.
Solution: (PR has been made to add this feature, but if you can't wait)
Add the following code to file RNMAILModule.java
if (options.hasKey("attachment") && !options.isNull("attachment")) {
i.putExtra(Intent.EXTRA_STREAM, Uri.parse(options.getMap("attachment").getString("path")));
}
When both Android and iOS work you should have something like this:
And here is the working code:
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: ['[email protected]'],
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 [email protected]');
}
})
})
.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;
------ OLD ANSWER BELOW ------
I never used this module before, but it looks like it expects absolute path of the file, however you are providing a file uri.
How are you obtaining this file uri?
Try using react-native-get-real-path module to see if it helps, you can find it here: react-native-get-real-path
i.e. convert your file uri to obtain real path, and use that as path
这篇关于React Native - 每封邮件发送照片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!