我知道这个问题以前曾被问过。但所有答案都不适合我。
有什么要求:
在 iOS 应用程序上,用户能够录制一个短音频文件(30 秒),然后使用 https 请求将其上传到服务器。
手机上的录音和临时保存效果很好。
但我无法让上传部分工作。
我在 API 端上传文件的代码如下。用
Postman
测试过,效果很好。文件已收到并按预期保存。[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 );
}
}
这是我上传文件的 Objective-C 代码:
-(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];
}
} 我得到的答案是:
response: {"code":500,"reason":"File is null"}
而不是
NSURLSessionDataTask
我尝试使用NSURLSessionUploadTask
但没有运气。我得到:
Failed to read the request form. Multipart body length limit 16384 exceeded
因为 Postman 可以很好地使用 API 端点上传文件。那么问题肯定出在iOS应用端。
任何想法可能是什么问题?
谢谢!
感谢@Paulw11提到不一致问题。
重新审视我两边的代码,意识到我在 iOS 表单上犯了一个错误,将
file
称为 userfile
。 API 需要file。所以这里应该有两个选择:Content-Disposition: form-data; name=\"userfile\";
至 file
,以便 API 识别它。
public async Task<IActionResult> UploadFile([FromForm(Name = "userfile")] IFormFile file, [FromForm(Name = "filename")] string filename){
//upload logic here
}
这解决了我的问题,文件现已上传!