- 内容简介
- 译者序
- 前言
- 第 1 章 安装配置新项目
- 第 2 章 Flexbox 布局介绍
- 第 3 章 用 React Native 开发一个应用
- 第 4 章 在 React Native 中使用导航
- 第 5 章 动画和滑动菜单
- 第 6 章 用 React Native 绘制 Canvas
- 第 7 章 使用 React Native 播放音频
- 第 8 章 你的第一个自定义视图
- 第 9 章 Flux 介绍
- 第 10 章 处理复杂的应用程序状态
- 第 11 章 使用 Node 来实现服务端 API
- 第 12 章 在 React Native 中使用文件上传
- 第 13 章 理解 JavaScript Promise
- 第 14 章 fetch 简介
- 第 15 章 在 iOS 中使用 SQLite
- 第 16 章 集成 Google Admob
- 第 17 章 React Native 组件国际化
- 附录 A React.js 快速介绍
- 附录 B Objective-C Primer
- 附录 C webpack 入门
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
React Native 文件上传的客户端
创建一个项目:
react-native init TestSample
编辑生成的 index.ios.js 文件,代码如下:
index.ios.js
'use strict';
var React = require('react-native'); var{
AppRegistry,
TouchableHighlight,
StyleSheet,
Text,
View,
NativeModules
} = React;
var TestSample = React.createClass({
getInitialState: function(){
return {
status: ""
}
},
onPress: function(){
var obj = {
uri: "data:http://example.com/banner.jpg",
uploadUrl: "http://192.168.100.7:3000/api/photo",
fileName: "banner.jpg",
mimeType: "application/jpeg"
};
NativeModules.FileTransfer.upload(obj, (err, res) => {
if (err ! = null){
this.setState({status: err});
}
else {
this.setState({status: "OK"});
}
})
},
render: function() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload, {'\n'} Cmd+D or shake for dev menu
</Text>
<TouchableHighlight onPress={this.onPress}>
<Text style={styles.button}>Upload</Text>
</TouchableHighlight>
<Text>{this.state.status}</Text>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
button: {
color: '#123456',
marginBottom: 5
}
});
和原来的文件不一样的地方就是,添加了上传文件部分的代码:
onPress: function(){
var obj = {
uri: "data:http://example.com/banner.jpg",
uploadUrl: "http://192.168.100.7:3000/api/photo",
fileName: "banner.jpg",
mimeType: "application/jpeg"
};
NativeModules.FileTransfer.upload(obj, (err, res) => {
if (err ! = null){
this.setState({status: err});
} else {
this.setState({status: "OK"});
}
})
}
如果需要上传一个远程文件,那就提供一个带有 uri 前缀的数据。阅读 RTCFileTransfer.m 文件,了解所有支持的上传文件前缀。
我们来创建 FileTransfer 的模块。它暴露出一个名为 upload 的方法。在 Xcode 中添加 RTCFile-Transfer.m 文件,步骤为:Your Project>Libraries>React>Base。
RTCFileTransfer.m
#import "RCTBridgeModule.h"
#import "RCTUtils.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <UIKit/UIKit.h>
@interface FileTransfer : NSObject <RCTBridgeModule>
- (NSMutableURLRequest *)getMultiPartRequest:(NSData *)data
serverUrl:(NSString *)server requestData:(NSDictionary *)
requestData mimeType:(NSString *)mimeType fileName:(NSString *)
fileName;
- (void)uploadAssetsLibrary:(NSDictionary *)input callback:(
RCTResponseSenderBlock)callback;
- (void)uploadUri:(NSDictionary *)input callback:(
RCTResponseSenderBlock)callback;
- (void)uploadFile:(NSDictionary *)input callback:(
RCTResponseSenderBlock)callback;
- (void)sendData:(NSData *)data withOptions:(NSDictionary *)input
callback:(RCTResponseSenderBlock)callback;
@end
@implementation FileTransfer RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(upload:(NSDictionary *)input callback:(
RCTResponseSenderBlock)callback)
{
NSString *uri = input[@"uri"]; if([uri hasPrefix:@"assets-library
"]){
[self uploadAssetsLibrary:input callback:callback];
}
else if([uri hasPrefix:@"data:"]){
[self uploadUri:input callback:callback];
}
else if([uri hasPrefix:@"file:"]){
[self uploadUri:input callback:callback];
}
else if ([uri isAbsolutePath]) {
[self uploadFile:input callback:callback];
} else{
callback(@[RCTMakeError(@"Unknown protocol for key: 'file'",
nil, nil)]);
}
}
- (void)uploadAssetsLibrary:(NSDictionary *)input callback:(
RCTResponseSenderBlock)callback
{
NSURL *assetUrl = [[NSURL alloc] initWithString:input[@"uri"]];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:assetUrl resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *rep = [asset defaultRepresentation];
CGImageRef fullScreenImageRef = [rep fullScreenImage];
UIImage *image = [UIImage imageWithCGImage:fullScreenImageRef];
NSData *fileData = UIImagePNGRepresentation(image);
[self sendData:fileData withOptions:input callback:callback];
// Byte *buffer = (Byte*)malloc(rep.size);
// NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0
length:rep.size error:nil];
//
// NSData *fileData = [NSData dataWithBytesNoCopy:buffer
length:buffered freeWhenDone:YES];
// NSDictionary* requestData = [input objectForKey:@"data"];
// NSMutableURLRequest* req = [self getMultiPartRequest:
fileData serverUrl:uploadUrl requestData:requestData
mimeType:mimeType fileName:fileName];
//
// NSHTTPURLResponse *response = nil;
// NSData *returnData = [NSURLConnection sendSynchronousRequest
:req returningResponse:&response error:nil];
// NSInteger statusCode = [response statusCode];
// NSString *returnString = [[NSString alloc] initWithData:
returnData encoding:NSUTF8StringEncoding];
//
// NSDictionary *res=[[NSDictionary alloc]
initWithObjectsAndKeys:[NSNumber numberWithInteger:
statusCode], @"status", returnString, @"data", nil];
//
// callback(@[res]);
} failureBlock:^(NSError *error) {
callback(@[RCTMakeError(@"Error loading library asset", nil,
nil)]);
}]; }
- (void)uploadFile:(NSDictionary *)input callback:(
RCTResponseSenderBlock)callback
{
NSString *filePath = input[@"uri"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
[self sendData:fileData withOptions:input callback:callback];
}
- (void)uploadUri:(NSDictionary *)input callback:(
RCTResponseSenderBlock)callback
{
NSString *dataUrlString = input[@"uri"];
NSURL *dataUrl = [[NSURL alloc] initWithString:dataUrlString];
NSData *fileData = [NSData dataWithContentsOfURL: dataUrl];
[self sendData:fileData withOptions:input callback:callback];
}
- (void)sendData:(NSData *)data withOptions:(NSDictionary *)input
callback:(RCTResponseSenderBlock)callback
{
NSString *fileName = input[@"fileName"];
NSString *mimeType = input[@"mimeType"];
NSString *uploadUrl = input[@"uploadUrl"];
NSDictionary* requestData = [input objectForKey:@"data"];
NSMutableURLRequest* req = [self getMultiPartRequest:data
serverUrl:uploadUrl requestData:requestData mimeType:mimeType
fileName:fileName];
NSHTTPURLResponse *response = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:req
returningResponse:&response error:nil];
NSInteger statusCode = [response statusCode];
NSString *returnString = [[NSString alloc] initWithData:
returnData encoding:NSUTF8StringEncoding];
NSDictionary *res=[[NSDictionary alloc] initWithObjectsAndKeys:[
NSNumber numberWithInteger:statusCode], @"status", returnString,
@"data", nil];
callback(@[[NSNull null], res]);
}
- (NSMutableURLRequest *)getMultiPartRequest:(NSData *)data
serverUrl:(NSString *)server requestData:(NSDictionary *)
requestData mimeType:(NSString *)mimeType fileName:(NSString *)
fileName
{
NSString* fileKey = @"file";
NSURL* url = [NSURL URLWithString:server];
NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:
url];
[req setHTTPMethod:@"POST"];
NSString* formBoundaryString = @"----react.file.transfer.form.
boundary";
NSString* contentType = [NSString stringWithFormat:@"multipart/
form-data; boundary=%@", formBoundaryString];
[req setValue:contentType forHTTPHeaderField:@"Content-Type"];
NSData* formBoundaryData = [[NSString stringWithFormat:@"--%@\r\n
", formBoundaryString] dataUsingEncoding:NSUTF8StringEncoding
];
NSMutableData* requestBody = [NSMutableData data];
for (NSString* key in requestData) {
id val = [requestData objectForKey:key];
if ([val respondsToSelector:@selector(stringValue)]) {
val = [val stringValue];
}
if (! [val isKindOfClass:[NSString class]]) {
continue;
}
[requestBody appendData:formBoundaryData];
[requestBody appendData:[[NSString stringWithFormat:@"Content-
Disposition: form-data; name=\"%@\"\r\n\r\n", key]
dataUsingEncoding:NSUTF8StringEncoding]];
[requestBody appendData:[val dataUsingEncoding:
NSUTF8StringEncoding]];
[requestBody appendData:[@"\r\n" dataUsingEncoding :
NSUTF8StringEncoding]];
}
[requestBody appendData:formBoundaryData];
[requestBody appendData:[[NSString stringWithFormat:@"Content-
Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",
fileKey, fileName] dataUsingEncoding:NSUTF8StringEncoding]];
if (mimeType ! = nil) {
[requestBody appendData:[[NSString stringWithFormat:@"Content-
Type: %@\r\n", mimeType] dataUsingEncoding:
NSUTF8StringEncoding]];
}
[requestBody appendData:[[NSString stringWithFormat:@"Content-
Length: %ld\r\n\r\n", (long)[data length]] dataUsingEncoding:
NSUTF8StringEncoding]];
NSData* afterFile = [[NSString stringWithFormat:@"\r\n--%@--\r\n
", formBoundaryString] dataUsingEncoding:NSUTF8StringEncoding
];
long long totalPayloadLength = [requestBody length] + [data
length] + [afterFile length];
[req setValue:[[NSNumber numberWithLongLong:totalPayloadLength]
stringValue] forHTTPHeaderField:@"Content-Length"];
[requestBody appendData:data];
[requestBody appendData:afterFile];
[req setHTTPBody:requestBody];
return req;
}
@end
程序运行后,当点击上传按钮上传图片后,可以在 Node.js 服务器的 uploads 文件夹下找到上传的 banner.jpg 文件。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论