草庐IT

ios - 解析 iOS 中图像下载的多部分响应

coder 2023-09-27 原文

在我的应用程序中,我从服务器下载图像作为多部分内容。在我的响应数据中,我得到了 2 个部分:一个是 json 内容,另一个是下载的文件。响应采用以下格式。

--poa89012-3212-1232-9201-fdsakjkj921
Content-Type: application/json; charset=utf-8
Content-Disposition: inline; name=info

{
  //json content
}

--poa89012-3212-1232-9201-fdsakjkj921
Content-Disposition: file; name=file; filename=photo.png
Content-Type: application/octet-stream

// File data
˘íë77íí77Í¥2008:02:11 11:32:512008:02:1
------

当我尝试获取 didReceiveResponse 中的 header 时,我无法处理这个包含 2 个部分的响应:它给出了内容类型为 multipart/mixed 的整个响应的 header 。请告诉我方法通过拆分 json 内容和文件内容来处理此响应。

最佳答案

我也确实遇到了 http-multipart response 的问题.我为 NSData 写了一个类别。代码如下:

NSData+MultipartResponses.h

#import <Foundation/Foundation.h>

@interface NSData (MultipartResponses)

- (NSArray *)multipartArray;
- (NSDictionary *)multipartDictionary;

@end

NSData+MultipartResponses.m

#import "NSData+MultipartResponses.h"

@implementation NSData (MultipartResponses)

static NSMutableDictionary *parseHeaders(const char *headers)
{
   NSMutableDictionary *dict=[NSMutableDictionary dictionary];
   int max=strlen(headers);
   int start=0;
   int cursor=0;
   while(cursor<max)
   {
      while((headers[cursor]!=':')&&(headers[cursor]!='='))
      {
         cursor++;
      }
      NSString *key=[[NSString alloc] initWithBytes:(headers+start) length:(cursor-start) encoding:NSASCIIStringEncoding];
      cursor++;

      while(headers[cursor]==' ')
      {
         cursor++;
      }
      start=cursor;
      while(headers[cursor]&&(headers[cursor]!=';')&&((headers[cursor]!=13)||(headers[cursor+1]!=10)))
      {
         cursor++;
      }

      NSString *value;
      if((headers[start]=='"')&&(headers[cursor-1]=='"'))
      {
         value=[[NSString alloc] initWithBytes:(headers+start+1) length:(cursor-start-2) encoding:NSASCIIStringEncoding];
      }
      else
      {
         value=[[NSString alloc] initWithBytes:(headers+start) length:(cursor-start) encoding:NSASCIIStringEncoding];
      }
      [dict setObject:value forKey:key];

      if(headers[cursor]==';')
      {
         cursor++;
      }
      else
      {
         cursor+=2;
      }

      while(headers[cursor]==' ')
      {
         cursor++;
      }
      start=cursor;
   }
   return dict;
}

- (NSDictionary *)multipartDictionaryWithBoundary:(NSString *)boundary
{
   NSMutableDictionary *dict=[NSMutableDictionary dictionary];

   const char *bytes=(const char *)[self bytes];
   const char *pattern=[boundary cStringUsingEncoding:NSUTF8StringEncoding];

   int cursor=0;
   int start=0;
   int max=[self length];
   int keyNo=0;
   while(cursor<max)
   {
      if(bytes[cursor]==pattern[0])
      {
         int i;
         int patternLength=strlen(pattern);
         BOOL match=YES;
         for(i=0; i<patternLength; i++)
         {
            if(bytes[cursor+i]!=pattern[i])
            {
               match=NO;
               break;
            }
         }
         if(match)
         {
            if(start!=0)
            {
               int startOfHeaders=start+2;
               int cursor2=startOfHeaders;
               while((bytes[cursor2]!=(char)0x0d)||(bytes[cursor2+1]!=(char)0x0a)||(bytes[cursor2+2]!=(char)0x0d)||(bytes[cursor2+3]!=(char)0x0a))
               {
                  cursor2++;
                  if(cursor2+4==max)
                  {
                     break;
                  }
               }
               if(cursor2+4==max)
               {
                  break;
               }
               else
               {
                  int lengthOfHeaders=cursor2-startOfHeaders;
                  char *headers=(char *)malloc((lengthOfHeaders+1)*sizeof(char));
                  strncpy(headers, bytes+startOfHeaders, lengthOfHeaders);
                  headers[lengthOfHeaders]=0;

                  NSMutableDictionary *item=parseHeaders(headers);

                  int startOfData=cursor2+4;
                  int lengthOfData=cursor-startOfData-2;

                  if(([item valueForKey:@"Content-Type"]==nil)&&([item valueForKey:@"filename"]==nil))
                  {
                     NSString *string=[[NSString alloc] initWithBytes:(bytes+startOfData) length:lengthOfData encoding:NSUTF8StringEncoding];
                     keyNo++;
                     [dict setObject:string forKey:[NSString stringWithFormat:@"%d", keyNo]];
                  }
                  else
                  {
                     NSData *data=[NSData dataWithBytes:(bytes+startOfData) length:lengthOfData];
                     [item setObject:data forKey:@"data"];
                     keyNo++;
                     [dict setObject:item forKey:[NSString stringWithFormat:@"%d", keyNo]];
                  }
               }
            }
            cursor=cursor+patternLength-1;
            start=cursor+1;
         }
      }
      cursor++;
   }

   return dict;
}

- (NSArray *)multipartArray
{
   NSDictionary *dict=[self multipartDictionary];
   NSArray *keys=[[dict allKeys] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
   NSMutableArray *array=[NSMutableArray array];
   for(NSString *key in keys)
   {
      [array addObject:dict[key]];
   }
   return array;
}

- (NSDictionary *)multipartDictionary
{
   const char *bytes=(const char *)[self bytes];
   int cursor=0;
   int max=[self length];
   while(cursor<max)
   {
      if(bytes[cursor]==0x0d)
      {
         break;
      }
      else
      {
         cursor++;
      }
   }
   char *pattern=(char *)malloc((cursor+1)*sizeof(char));
   strncpy(pattern, bytes, cursor);
   pattern[cursor]=0x00;
   NSString *boundary=[[NSString alloc] initWithCString:pattern encoding:NSUTF8StringEncoding];
   free(pattern);
   return [self multipartDictionaryWithBoundary:boundary];
}

@end

关于ios - 解析 iOS 中图像下载的多部分响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22095186/

有关ios - 解析 iOS 中图像下载的多部分响应的更多相关文章

  1. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  4. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  5. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  6. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  7. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  8. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  9. ruby-on-rails - 我更新了 ruby​​ gems,现在到处都收到解析树错误和弃用警告! - 2

    简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und

  10. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

随机推荐