【问题标题】:how to upload image of type png on server如何在服务器上上传png类型的图像
【发布时间】:2015-06-21 07:59:39
【问题描述】:

我的问题可能被标记为重复,但经过大量解决方案后,我仍然无法弄清楚我哪里出错了。请帮忙。

我的图片名称是“image.png”。请务必指定应包含在 BoundaryConstant 中的内容。我刚刚从某个网站复制了它。

// // create request NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; NSURL* requestURL = [NSURL URLWithString:@"http://....."]; [request setURL:requestURL]; [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; [request setHTTPShouldHandleCookies:NO]; [request setTimeoutInterval:30]; [request setHTTPMethod:@"POST"]; NSString *BoundaryConstant = @"----------V2ymHFg03ehbqgZCaKO6jy"; NSString *filename = @"image"; // set Content-Type in HTTP header NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", BoundaryConstant]; [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; // post body NSMutableData *body = [NSMutableData data]; // add image data NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:@"image.png"]); if (imageData) { [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.png\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[NSData dataWithData:imageData]]; [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; } [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]]; // setting the body of the post to the reqeust [request setHTTPBody:body]; // set the content-length NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[body length]]; [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; // set URL [request setURL:requestURL]; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; NSLog(@"Ret: %@",returnString);

【问题讨论】:

    标签: ios


    【解决方案1】:

    有额外的\r\n 字符(请参阅下面的第 2 点),但其他方面看起来还不错。如果不查看服务器代码、NSURLResponse 对象或 NSError 对象,我们无法诊断可能出了什么问题。

    一些细节:

    1. 我不会在边界的开头包含破折号。如果不出意外,就很难将领先的-- 与实际边界区分开来。

    2. 你在边界前写了一个额外的\r\n。我会替换

      [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
      

      [body appendData:[[NSString stringWithFormat:@"--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
      

      并替换

      [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
      

      [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
      

      按原样(特别是在您添加图像数据的位置,\r\n,然后是\r\n--%@--\r\n),您在上传的末尾添加了额外的两个字节(即\r\n)图片。这通常不会导致问题(图像通常仍然有效),但它不正确。

    3. 您通常不必设置Content-Length 标头。

    4. 不要使用同步请求。使用sendAsynchronousRequest

    5. 您将 nil 用于 responseerror 对象。如果您这样做,那么您可以执行的诊断将受到极大限制。你在瞎飞。应始终检查生成的 NSURLResponseNSError 对象。

    6. 如果不查看服务器代码,我们无法判断此上传是否可行。特别是,我发现您使用名为 filename 且值为 image 的变量作为字段的 name 有点令人困惑。但是如果你在服务器上的$_FILES(或者如果不使用PHP,不管它正在寻找什么字段名)正在寻找image,那很好。这只是变量名的混淆/误导性选择。我可能会将该变量称为 fieldName 或类似的名称。

      最重要的是,$_FILES 是否正在寻找一个名为 image 的字段名称?

    7. 你有一行说:

      [body appendData:[NSData dataWithData:imageData]];
      

      可能只是:

      [body appendData:imageData];
      

      无需创建新的NSData

    8. 我会删除对setURL 的第二次调用。没必要。

    9. 您正在加载image.png,将其转换为UIImage,然后使用UIImagePNGRepresentation 得到NSData。这可以工作,但效率非常低。只需将文件内容直接加载到NSData,完全绕过UIImage

      另外,如果找不到图像,我建议您记录错误消息。现在,它会简单地跳过添加图像的步骤(意味着它会静默发送请求,而不是告诉你是否有问题)。

    10. 您应该在Charles 之类的工具中查看此请求。如果您要在准备请求时了解此级别的详细信息,则应在请求发出时对其进行检查。

    11. 我建议你使用类似AFNetworking 的东西,它可以让你摆脱这些杂草。如果您想自己执行此操作,请参阅https://stackoverflow.com/a/24252378/1271826

    【讨论】:

    • 谢谢兄弟!在第 6 点的上下文中,请告诉我名称中传递了什么?我的图像名称是 image.png,所以我只使用了“图像”这个词。也让我知道 BoundaryConstant 是否可以是任何常数。为什么做这么长?
    • 当上传不是文件时,有两个我们关心的“名称”。 “字段名称”是上传文件时服务器代码正在寻找的预定标识符。将其视为 Web 服务 API 的一部分。因此,请查看服务器期望的字段名称。另一方面,“文件名”是要上传的文件的名称,这可能会在运行时根据用户选择上传的文件而改变。这里令人困惑的是,您的变量 filename 实际上被用作字段名称。哈哈。
    • 是的,边界字符串可以是任何字符串值,但您要确保它是一个字符序列,在发送的字段值中从不出现。如果边界字符串只是“x”,那么它在任何随机值中出现的概率是 256 分之一。如果边界字符串为“xx”,则该机会下降到 65,536 中的 1。如果是“xxxx”,则为 40 亿分之 1。等等。因此,通过使这个字符串相当长,它在天文数字上不太可能出现在字段值中。
    • 您应该在客户端代码中使用与服务器代码中的字段名称相匹配的字段名称。那么你的服务器代码使用什么字段名呢?
    • 我的代码终于可以工作了。造成所有麻烦的是字段名。感谢 Rob 在整个过程中帮助我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    • 2012-01-18
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    相关资源
    最近更新 更多