ios - Grails多部分服务流意外结束

标签 ios grails multipartform-data nsurlrequest

我正在编写一个ios应用程序,我需要将照片从我的应用程序发送到grails服务器。
在ios中,我这样做:

+(void)sendPhoto:(NSData *)data withName:(NSString *)name onController:(UIViewController<MERequestDelegate> *)controller
{
    MERequest *request = [[MERequest alloc] init];
    request.delegate = controller;

    //User
    User *user = [User loadUser];

    //Creazione del BOdy della richiesta Multipart
    NSMutableData *body = [[NSMutableData alloc] init];

    //Token
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", kBOUNDARY] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"token\"\r\n\r\n%@", user.token] dataUsingEncoding:NSUTF8StringEncoding]];

    //Immagine
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", kBOUNDARY] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"photo\"; filename=\"%@.jpg\"\r\n", name] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: image/jpg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:data]];

    //Chiusura Body
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", kBOUNDARY] dataUsingEncoding:NSUTF8StringEncoding]];

    [request requestMultipartAtUrl:[NSString stringWithFormat:@"%@WS/sendMultipart", [SettingsUtils webAppUrl]] withData:body];
}

-(void)requestMultipartAtUrl:(NSString *)url withData:(NSData *)body
{
    //NSError *error;
    NSString *stringToBeSent;
    _timeOutSecond = 10;

    stringToBeSent = [[NSString alloc] initWithFormat:@"%@", url];
    NSLog(@"URL: %@", stringToBeSent);

    //Url
    self.theUrl = [NSURL URLWithString:[stringToBeSent stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    //Request
    self.mutableRequest = [NSMutableURLRequest requestWithURL:self.theUrl];

    //Header
    [self.mutableRequest setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
    [self.mutableRequest setHTTPShouldHandleCookies:NO];
    [self.mutableRequest setTimeoutInterval:30];
    [self.mutableRequest setHTTPMethod:@"POST"];
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kBOUNDARY];
    [self.mutableRequest addValue:contentType forHTTPHeaderField:@"Content-Type"];
    [self.mutableRequest addValue:[NSString stringWithFormat:@"%d", [body length]] forHTTPHeaderField:@"Content-Length"];

    //Data
    [self.mutableRequest setHTTPBody:body];

    //Set Timer
    if(_timer == NULL){
        _timer = [NSTimer scheduledTimerWithTimeInterval:_timeOutSecond
                                              target:self
                                            selector:@selector(requestTimedOut:)
                                            userInfo:nil
                                             repeats:NO];
    }

    //Create the connection
    _connection = [[NSURLConnection alloc] initWithRequest:self.mutableRequest delegate:self];
}

在Grails中,我有一个只有println的空白方法:
def sendMultipart = {
    println("Send")
}

当我启动应用程序并创建请求时,grails上出现此错误:
2014-02-11 23:28:46,925 [http-8080-1] ERROR [org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/SimplifyWFA].[default](StandardWrapperValve.java:281)] - Servlet.service() for servlet default threw exception
org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162)
    at org.codehaus.groovy.grails.web.multipart.ContentLengthAwareCommonsMultipartResolver.parseRequest(ContentLengthAwareCommonsMultipartResolver.java:48)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:138)
    at org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingInfo.getResolvedRequest(DefaultUrlMappingInfo.java:173)
    at org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingInfo.tryMultipartParams(DefaultUrlMappingInfo.java:163)
    at org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingInfo.checkDispatchAction(DefaultUrlMappingInfo.java:140)
    at org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingInfo.getActionName(DefaultUrlMappingInfo.java:122)
    at org.codehaus.groovy.grails.web.mapping.AbstractUrlMappingInfo.populateParamsForMapping(AbstractUrlMappingInfo.java:94)
    at org.codehaus.groovy.grails.web.mapping.AbstractUrlMappingInfo.configure(AbstractUrlMappingInfo.java:44)
    at org.codehaus.groovy.grails.plugins.springsecurity.AnnotationFilterInvocationDefinition.configureMapping(AnnotationFilterInvocationDefinition.java:144)
    at org.codehaus.groovy.grails.plugins.springsecurity.AnnotationFilterInvocationDefinition.determineUrl(AnnotationFilterInvocationDefinition.java:82)
    at org.codehaus.groovy.grails.plugins.springsecurity.AbstractFilterInvocationDefinition.getAttributes(AbstractFilterInvocationDefinition.java:80)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:172)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:112)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    at org.codehaus.groovy.grails.plugins.springsecurity.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:40)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.codehaus.groovy.grails.plugins.springsecurity.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:168)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:69)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.codehaus.groovy.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:65)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
    at java.lang.Thread.run(Thread.java:695)
Caused by: org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:381)
    at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:155)
    ... 59 more
Caused by: org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
    at org.apache.commons.fileupload.MultipartStream.readHeaders(MultipartStream.java:539)
    at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:976)
    at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.hasNext(FileUploadBase.java:1040)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:356)
    ... 61 more

为什么会出现此错误?是iOS的错吗?还是我错过了grails设置?

谢谢!

最佳答案

我解决了这个问题!
问题出在这里:

//Chiusura Body
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", kBOUNDARY] dataUsingEncoding:NSUTF8StringEncoding]];

多部分封闭体在边界后需要“-”:
@"\r\n--%@--"

我们走了:D

感谢:Multipart Description

关于ios - Grails多部分服务流意外结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21714527/

相关文章:

ios - Facebook 对我的应用程序的邀请不起作用

ios - 如何让 Charles 在 SSL 连接上使用 Xcode 7?

grails - 如何从 Controller 响应相同的gsp View ?

java - 在 Spring boot 和 REST API 中上传 multipart/form-data 文件

ios - 面向 Swift 协议(protocol)的网络代码导致 Xcode 崩溃

ios - 企业 ios 应用程序中的崩溃日志

tomcat - 将 .war 部署到 OpenShift 找不到 404 错误

string - 什么函数用于格式化/替换 Grails/Groovy 中字符串中的 {0} {1} 参数?

eclipse - 在 Spring webapp 中处理 MaxUploadSizeExceededException

java - 将 java 文件转换为 play.db.jpa.Blob