如何向Azure Function同时上传文件与JSON上下文数据?
问题根源分析
你当前的问题主要出在请求格式错误和后端解析逻辑矛盾两个方面:
- 请求的
Content-Type同时指定了application/json和multipart/form-data,这属于无效的HTTP头,Multipart请求只能以multipart/form-data作为Content-Type。 - 后端先调用
ReadFromJsonAsync会将请求体流完全读取,后续再解析Multipart时流已处于末尾,无法获取文件数据;同时错误地期望从JSON中读取整个UploadCommand,但Multipart请求的上下文数据和文件是分部分存储的。
可行解决思路
1. 修正VS Code Rest Client请求格式
构造标准的Multipart请求,将JSON上下文和文件分为两个独立的表单部分:
POST http://localhost:7071/api/upload Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="command" Content-Type: application/json { "culture": "zh-CN", "status": "active", "accessType": "public", "folders": [], "fileTypes": ["png"], "allowOverrides": true } ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="files"; filename="2020-04-29.png" Content-Type: image/png < C:\Users\enend\OneDrive\Pictures\Screenshots\2020-04-29.png ------WebKitFormBoundary7MA4YWxkTrZu0gW--
2. 修改后端解析逻辑
先完整解析Multipart表单,再分别提取JSON上下文和文件部分,避免流读取冲突:
private async Task<UploadCommand?> GetCommandAsync(HttpRequestData httpRequest) { try { // 先解析整个Multipart表单 var parser = await MultipartFormDataParser.ParseAsync(httpRequest.Body); // 提取JSON上下文部分 var commandPart = parser.Parameters.FirstOrDefault(p => p.Name == "command"); if (commandPart == null || string.IsNullOrEmpty(commandPart.Data)) return null; var command = JsonSerializer.Deserialize<UploadCommand>(commandPart.Data, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); if (command == null) return null; // 将Multipart中的文件赋值给Command command.Files = parser.Files.ToList(); return command; } catch(Exception ex) { _log.LogError(ex.ToString()); return null; } }
3. 调整UploadCommand模型
因为Files属性现在来自Multipart文件部分而非JSON,可移除对应的JSON序列化标记(保留也不影响,但逻辑更清晰):
public class UploadCommand { // 移除JSON标记,文件来自Multipart表单 public IEnumerable<FilePart> Files { get; set; } = new List<FilePart>(); [JsonPropertyName("culture")] public string? Culture { get; set; } [JsonPropertyName("status")] public string? Status { get; set; } [JsonPropertyName("accessType")] public string? AccessType { get; set; } [JsonPropertyName("folders")] public IEnumerable<Folder>? Folders { get; set; } [JsonPropertyName("fileTypes")] public IEnumerable<string>? FileTypes { get; set; } [JsonPropertyName("allowOverrides")] public bool AllowOverride { get; set; } }
额外注意事项
- 确保已通过NuGet安装
MultipartDataMediaFormatter.AspNetCore(如果使用该库解析Multipart); - Azure Function默认允许
multipart/form-data请求,无需额外配置,若有自定义路由限制需检查; - 请求中的boundary值要和实际分隔符完全匹配,避免解析失败。
内容的提问来源于stack exchange,提问作者EnenDaveyBoy
相关产品推荐
相关产品推荐

