You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS端NSURLSessionDataTask上传音频文件至服务器失败排查

iOS音频上传问题排查与解决

问题背景

iOS应用录制30秒音频后通过HTTPS上传至服务器,录制和本地存储功能正常,但上传环节失败。服务器API经Postman测试可正常接收文件,iOS端调用返回错误。

服务器端API代码

[HttpPost]
public async Task<IActionResult> UploadFile([FromForm] IFormFile file, [FromForm] string name)
{
    try
    {
        if(webHostEnvironment == null)
        {
            throw new SqlNullValueException("webHostEnvironment is null");
        }

        if (webHostEnvironment.ContentRootPath == null)
        {
            throw new SqlNullValueException("webHostEnvironment.ContentRootPath is null");
        }

        if(file == null)
        {
            throw new SqlNullValueException("File is null");
        }

        String path = Path.Combine(webHostEnvironment.ContentRootPath,  "uploads");              
        if (file.Length > 0)
        {
            string filePath = Path.Combine(path, file.FileName);
            using (Stream fileStream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(fileStream);
            }
        }
        return BuildResponse(Ok().StatusCode, name);
    }
    catch(Exception ex)
    {
        throw new Exception(ex.Message );
    }
}

iOS端原上传代码

-(void)uploadFile:(NSData*)fileData{
if(fileData != nil){
    NSString *fileName = self.temporaryRecFile.path.lastPathComponent;
    NSString *urlString = @"some url";//upload file url
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:@"POST"];
    NSString *boundary = @"---------------1234567890";
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request addValue:contentType forHTTPHeaderField:@"Content-Type"];
    
    
    NSMutableData *bodyData = [[NSMutableData alloc] init];
    [bodyData appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [bodyData appendData:[[NSString stringWithString:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\"\r\n", fileName]] dataUsingEncoding:NSUTF8StringEncoding]];
    [bodyData appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [bodyData appendData:[NSData dataWithData:fileData]];
    [bodyData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
    [request setHTTPBody:bodyData];
            
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        dispatch_async(dispatch_get_main_queue(), ^{
            
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
            NSInteger responseStatusCode = [httpResponse statusCode];
            
            if(error != nil)
                NSLog(@"error uploading file %@", error.localizedDescription);
            else{
                NSLog(@"response: %lu", responseStatusCode);
                NSLog(@"response: %@", data);
                NSLog(@"response: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
            }
        });
    }];
    
    [dataTask resume];
}

错误1:返回{"code":500,"reason":"File is null"}

原因

服务器API接收的表单字段名为*file*(对应代码[FromForm] IFormFile file),但iOS端代码中设置的字段名为*userfile*(对应代码name=\"userfile\"),字段名不匹配导致服务器无法识别上传文件,返回文件为空错误。同时原代码未添加服务器要求的name参数,也会影响接口正常解析。

解决办法

修改iOS端表单字段名,补充name参数,同时修正multipart格式的边界符开头(原代码多了前置换行):

// 修正后的bodyData构建逻辑
NSMutableData *bodyData = [[NSMutableData alloc] init];
NSString *boundary = @"---------------1234567890";

// 添加服务器要求的name字段
[bodyData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[bodyData appendData:[@"Content-Disposition: form-data; name=\"name\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[bodyData appendData:[@"audio_record" dataUsingEncoding:NSUTF8StringEncoding]]; // 替换为实际业务需要的name值
[bodyData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

// 修正file字段名,匹配服务器要求
[bodyData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[bodyData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[bodyData appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[bodyData appendData:fileData];
[bodyData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

错误2:改用NSURLSessionUploadTask后返回Failed to read the request form. Multipart body length limit 16384 exceeded

原因

ASP.NET Core默认限制multipart表单体长度为16KB(16384字节),30秒音频文件大小通常超过该阈值;同时iOS端使用UploadTask时若未正确设置请求头,可能导致服务器误触发长度校验。

解决办法

  1. 服务器端调整配置:在Program.cs(或Startup.cs)中修改multipart长度限制:
builder.Services.Configure<FormOptions>(options =>
{
    options.MultipartBodyLengthLimit = 10 * 1024 * 1024; // 设置为10MB,可根据实际需求调整
});
  1. iOS端确保请求头正确:使用UploadTask时,需保持Content-Type头和dataTask一致,避免格式错误:
// 使用UploadTask时的请求头设置示例
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
NSString *boundary = @"---------------1234567890";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request addValue:contentType forHTTPHeaderField:@"Content-Type"];

// 后续上传逻辑保持与修正后的dataTask一致

额外注意事项

  • 确保iOS端urlString替换为实际服务器上传地址。
  • 小文件测试时可打印bodyData的字符串形式,对比Postman生成的请求体,确保格式完全一致。
  • 补充网络异常处理逻辑,比如超时、网络不可用等场景。

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:11:14