是否可以将视频上传到服务器?我知道图像是可能的。 如果有人可以指出我正确的方向,那将是非常棒的。
由于
答案 0 :(得分:17)
2015年8月编辑
这个答案现在已经过时了。在撰写本文时,没有太多选项,视频的尺寸相对较小。
如果您现在正在考虑这样做,我会使用AFNetworking
这使得这更简单。它将从文件中流式传输上传而不是将其全部保存在内存中,并且还支持新的Apple后台上传任务。
文档:https://github.com/AFNetworking/AFNetworking#creating-an-upload-task
-
是的,这是可能的,这就是我的方式。
实现以下在媒体选择器完成时运行的功能。
- (NSData *)generatePostDataForData:(NSData *)uploadData
{
// Generate the post header:
NSString *post = [NSString stringWithCString:"--AaB03x\r\nContent-Disposition: form-data; name=\"upload[file]\"; filename=\"somefile\"\r\nContent-Type: application/octet-stream\r\nContent-Transfer-Encoding: binary\r\n\r\n" encoding:NSASCIIStringEncoding];
// Get the post header int ASCII format:
NSData *postHeaderData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
// Generate the mutable data variable:
NSMutableData *postData = [[NSMutableData alloc] initWithLength:[postHeaderData length] ];
[postData setData:postHeaderData];
// Add the image:
[postData appendData: uploadData];
// Add the closing boundry:
[postData appendData: [@"\r\n--AaB03x--" dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
// Return the post data:
return postData;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
//assign the mediatype to a string
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
//check the media type string so we can determine if its a video
if ([mediaType isEqualToString:@"public.movie"]){
NSLog(@"got a movie");
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSData *webData = [NSData dataWithContentsOfURL:videoURL];
[self post:webData];
[webData release];
}
对于帖子功能我有这样的东西我从其他地方得到的(对不起,我不知道我在哪里找到它):
- (void)post:(NSData *)fileData
{
NSLog(@"POSTING");
// Generate the postdata:
NSData *postData = [self generatePostDataForData: fileData];
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
// Setup the request:
NSMutableURLRequest *uploadRequest = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.example.com:3000/"] cachePolicy: NSURLRequestReloadIgnoringLocalCacheData timeoutInterval: 30 ] autorelease];
[uploadRequest setHTTPMethod:@"POST"];
[uploadRequest setValue:postLength forHTTPHeaderField:@"Content-Length"];
[uploadRequest setValue:@"multipart/form-data; boundary=AaB03x" forHTTPHeaderField:@"Content-Type"];
[uploadRequest setHTTPBody:postData];
// Execute the reqest:
NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:uploadRequest delegate:self];
if (conn)
{
// Connection succeeded (even if a 404 or other non-200 range was returned).
NSLog(@"sucess");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Got Server Response" message:@"Success" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
else
{
// Connection failed (cannot reach server).
NSLog(@"fail");
}
}
上面的代码片段构建了http post请求并提交了它。如果你想要体面的错误处理并考虑使用允许异步上传的库(在github上有一个),你将需要修改它
还要注意上面服务器url上的端口:3000,我发现在开发模式下我可以很容易地在默认端口3000上启动rails服务器进行错误测试,这样我就可以看到用于调试目的的请求参数了
希望这有帮助
答案 1 :(得分:3)
由于iOS8不需要使用第三方库,您可以直接从文件中流式传输视频,当您尝试从文件加载视频时上传更大的视频时,这会解决关键的内存错误:
// If video was returned by UIImagePicker ...
NSURL *videoUrl = [_videoDictionary objectForKey:UIImagePickerControllerMediaURL];
NSMutableURLRequest *request =[[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:VIDEO_UPLOAD_LINK]];
[request addValue:@"video" forHTTPHeaderField: @"Content-Type"];
[request setHTTPMethod:@"POST"];
NSInputStream *inputStream = [[NSInputStream alloc] initWithFileAtPath:[videoUrl path]];
[request setHTTPBodyStream:inputStream];
self.uploadConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
iOS7还提供了出色的NSURLSeession / NSURLSessionUploadTask组合解决方案,它不仅让您直接从文件中流式传输,而且还可以将任务委派给iOS进程,这样就可以上传完成即使您的应用已关闭。 它需要更多的编码,我没有时间在这里写它(你可以谷歌它)。
以下是最重要的部分:
在后台支持中配置音频会话:
- (NSURLSession *)urlSession {
if (!_urlSession) {
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
NSString *bundleId = infoDict[@"CFBundleIdentifier"];
NSString *label = [NSString stringWithFormat:@"ATLoggerUploadManager_%@", bundleId];
NSURLSessionConfiguration *conf = (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) ? [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:label] : [NSURLSessionConfiguration backgroundSessionConfiguration:label];
conf.allowsCellularAccess = NO;
_urlSession = [NSURLSession sessionWithConfiguration:conf delegate:self delegateQueue:self.urlSessionQueue];
_urlSession.sessionDescription = @"Upload log files";
}
return _urlSession;
}
上传任务方法:
- (NSURLSessionUploadTask *)uploadTaskForFilePath:(NSString *)filePath session:(NSURLSession *)session {
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error = nil;
// Consruct request:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"POST"];
NSString *finalUrlString = [self.uploadURL absoluteString];
if (self.uploadUserId) {
[request setValue:self.uploadUserId forHTTPHeaderField:@"X-User-Id"];
finalUrlString = [finalUrlString stringByAppendingFormat:@"?id=%@", self.uploadUserId];
}
[request setURL:[NSURL URLWithString:finalUrlString]];
/*
It looks like this (it only works if you quote the filename):
Content-Disposition: attachment; filename="fname.ext"
*/
NSString *cdh = [NSString stringWithFormat:@"attachment; filename=\"%@\"", [filePath lastPathComponent]];
[request setValue:cdh forHTTPHeaderField:@"Content-Disposition"];
error = nil;
unsigned long fileSize = [[fm attributesOfItemAtPath:filePath error:&error] fileSize];
if (!error) {
NSString *sizeInBytesAsString = [NSString stringWithFormat:@"%lu", fileSize];
[request setValue:sizeInBytesAsString forHTTPHeaderField:@"X-Content-Length"];
}
NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileUrl];
uploadTask.taskDescription = filePath;
return uploadTask;
}
上传功能:
[self.urlSession getTasksWithCompletionHandler:^(NSArray * dataTasks,NSArray * uploadTasks,NSArray * downloadTasks){
NSMutableDictionary *tasks = [NSMutableDictionary new];
int resumed_running_count = 0;
int resumed_not_running_count = 0;
int new_count = 0;
// 1/2. Resume scheduled tasks:
for(NSURLSessionUploadTask *task in uploadTasks) {
//MILogInfo(@"Restored upload task %zu for %@", (unsigned long)task.taskIdentifier, task.originalRequest.URL);
if (task.taskDescription) {
[tasks setObject:task forKey:task.taskDescription];
}
BOOL isRunning = (task.state == NSURLSessionTaskStateRunning);
if (!isRunning) {
resumed_not_running_count++;
}else{
resumed_running_count++;
}
[task resume];
}
// 2/2. Add tasks / files not scheduled yet:
NSString *uploadFilePath = nil;
// already uploading:
if (![tasks valueForKey:uploadFilePath]) {
NSURLSessionUploadTask *uploadTask = [self uploadTaskForFilePath:uploadFilePath session:_urlSession];
new_count++;
[uploadTask resume];
}
}];
后台会话需要UIApplecation委托(实施AppDelegate回调:
(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void(^)())completionHandler {
NSLog(@"Background URL session needs events handled: %@", identifier);
completionHandler();
}
答案 2 :(得分:2)
看看UIImagePickerController。 从3.0开始,您可以选择拍摄视频或选择现有视频。根据文档,你在电影上限制为最多10分钟:
答案 3 :(得分:0)
NSURL *urlvideo = [info objectForKey:UIImagePickerControllerMediaURL];
NSString *urlString=[urlvideo path];
NSLog(@"urlString=%@",urlString);
NSString *str = [NSString stringWithFormat:@"you url of server"];
NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setFile:urlString forKey:@"key foruploadingFile"];
[request setRequestMethod:@"POST"];
[request setDelegate:self];
[request startSynchronous];
NSLog(@"responseStatusCode %i",[request responseStatusCode]);
NSLog(@"responseStatusCode %@",[request responseString]);