- 内容简介
- 译者序
- 前言
- 第 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 文件。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论