如何将文件提交到 ASP.NET 核心应用程序
How to submit a file to an ASP.NET Core application
我有一个 ASP.NET 应用程序,它提供了一个简单的表单来上传文件(图像)。看起来像这样:
public IActionResult Process()
{
return View();
}
[HttpPost]
public IActionResult Process(List<IFormFile> files)
{
var telemetry = new TelemetryClient();
try
{
var result = files.Count + " file(s) processed " + Environment.NewLine;
foreach (var file in files)
{
result += file.FileName + Environment.NewLine;
var memoryStream = new MemoryStream();
file.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var binaryReader = new BinaryReader(memoryStream);
var bytes = binaryReader.ReadBytes((int)memoryStream.Length);
var imageInformation = ImageService.ProcessImage(bytes);
ImageService.SaveImage(imageInformation.Result, bytes, file.FileName.Substring(file.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1));
}
return View((object)result);
}
catch (Exception ex)
{
telemetry.TrackException(ex);
throw;
}
}
应用程序中的此表单工作正常。问题是我想使用 Microsoft Flow 将进入 SharePoint 库的文件提交到上面定义的 Web 应用程序。
我有文件流设置,它 运行s 并且没有出错,但是当我查看 HTTP 操作结果的主体时,它说已处理 0 个文件并且没有完成任何事情。
我设置的流程是
- 创建文件 (SharePoint) 时(这是指向特定的文档库
- Http (Http),方法:Post,Uri(指向我的应用程序),正文:来自上述 SharePoint 步骤的文件内容。
正如我提到的,这是发布到站点,但不能以 ASP.NET 方法可以处理的方式传递文件,因此它不会处理任何内容。我怎样才能更改流程或 Post 方法,使其正常工作。
更新了新信息
我已经用一个非常小的图像试过了,所以我可以获得一些额外的请求信息。使用浏览器中的表单我尝试了这个并使用 Fiddler 获得以下请求原始结果:
POST https://os-gbsphotoretain.azurewebsites.net/Image/Process HTTP/1.1
Host: os-gbsphotoretain.azurewebsites.net
Connection: keep-alive
Content-Length: 924
Pragma: no-cache
Cache-Control: no-cache
Origin: https://os-gbsphotoretain.azurewebsites.net
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarySjQVgrsvAqJYXmST
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://os-gbsphotoretain.azurewebsites.net/Image/Process
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: _ga=GA1.3.955734319.1501514097; ai_user=UkqSf|2017-07-31T15:17:38.409Z; ARRAffinity=1628d46398b292eb2e3ba76b4b0f1eb1e30abd9bd1036d7a90b9c51f7baa2306; ai_session=/fPFh|1502738361594.15|1502738361594.15
------WebKitFormBoundarySjQVgrsvAqJYXmST
Content-Disposition: form-data; name="files"; filename="printer.jpg"
Content-Type: image/jpeg
JFIF ` ` C
$.' ",#(7),01444'9=82<.342 C
2!!22222222222222222222222222222222222222222222222222 "
} !1AQa "q2 #B R br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
w !1AQ aq"2 B #3R br
% &'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?
+X K 21 c Z ] ӥg v ; : P I f > m;] ֬u nm ` Q 1 P6 s 9 |b r| G
------WebKitFormBoundarySjQVgrsvAqJYXmST--
通过流处理相同的图像,我得到以下作为流中的正文:
{
"$content-type": "image/jpeg",
"$content": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAQABADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD1C9EMuqzGK1juS+3P7rccgc4yMYxjv1q/ol0I4bfTpQVniXaoyDuQHjoTg7ccGsDU7O+0+xEdoJfMUKiKE84MB/dJ5B9mzj6VneFtO1271qx1G+hubaGBjmCSUfMSMZZQNoxzgDnPfGKqcnypEJW1R//Z"
}
所以看起来流程正在提交为 JSON。我现在将尝试一些额外的处理作为测试,但如果有人知道我可以在 Web 应用程序中放入什么来处理这个问题,我将不胜感激。
我添加了一个新方法(见下文),当我 运行 它在本地传递 Flow 所说的字符串是正文时,它就起作用了。但是当我 运行 从流程中得到它时,我在 DeserializeObject 行中得到 value cannot be null 错误。如何获取 Flow 传入的信息。
[HttpPost]
public IActionResult ProcessJson(string json)
{
var telemetry = new TelemetryClient();
try
{
var result = "JSON processed " + Environment.NewLine;
var details = (dynamic)Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var content = (string) details["$content"];
var bytes = Convert.FromBase64String(content);
ProcessBytes(bytes, "jpeg");
return View("Process", result);
}
catch (Exception ex)
{
telemetry.TrackException(ex);
throw;
}
}
我也尝试过使用此签名的方法,但运气不佳,要么它以 null 形式出现
[HttpPost]
public IActionResult ProcessJson([FromBody]FlowFile file)
{
...
}
public class FlowFile
{
[JsonProperty(PropertyName = "$content-type")]
public string ContentType { get; set; }
[JsonProperty(PropertyName = "$content")]
public string Content { get; set; }
}
我添加了一些中间件,这样我就可以得到原始的 Request.Body,最终结果就是这样。我不确定这等同于什么。

�����JFIF��`�`�����C�		

 $.' ",#(7),01444'9=82<.342���C			

2!!22222222222222222222222222222222222222222222222222�����"��������������	
�������}�!1AQa"q2���#B��R��br�	
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�����������������������������������������������������������������������������������	
������w�!1AQaq"2�B����	#3R�br�
�%�&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�����������������������������������������������������������������������������?������+X�K�����21�c�Z��]�ӥg�v��;�:����������P����I�f�>���m;]�֬u�nm���`�Q�1�P6�s�9�|b�r|���G�
不使用 List<IFormFile>
参数,而是访问 HttpContext.Request
中的 Files
属性。
好吧,我有点不清楚文件是如何发送的:它是 json object 之前文件被转换为 base64 字符串还是文件内容? (htmlheaders为指标)
如果你有 json 理论你可以做:
var parsedFileContent = Newtonsoft.Json.JsonConvert.DeserializeObject<FlowFile>(json);
而不是
var details = (dynamic)Newtonsoft.Json.JsonConvert.DeserializeObject(json);
它应该有效,当且仅当 ;),你发布的内容是正确的
{
"$content-type": "image/jpeg",
"$content": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAQABADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD1C9EMuqzGK1juS+3P7rccgc4yMYxjv1q/ol0I4bfTpQVniXaoyDuQHjoTg7ccGsDU7O+0+xEdoJfMUKiKE84MB/dJ5B9mzj6VneFtO1271qx1G+hubaGBjmCSUfMSMZZQNoxzgDnPfGKqcnypEJW1R//Z"
}
只要确保 json 是单行字符串(确保没有像 \n 或类似的隐藏字符)
另一方面,在您的 Fidler 捕获中,您有:
Content-Type: multipart/form-data;
所以正确的方法是 IFormFile
所以提供的信息有点误导。您可以尝试传递更多的错误日志吗? "object reference not sent to an instance of an object error" 非常普遍,通常这些类型的错误会通过堆栈跟踪缩小范围。
我终于得到了这份工作。我需要做的是直接读取原始请求流,而该流就是图像。 Flow 所说的关于以 Base64 编码 JSON 字符串提交图像的所有内容都不正确。我无法将其绑定到任何参数或作为 Request.Form.Files,但我可以直接读取流并直接从中保存图像。
我有一个 ASP.NET 应用程序,它提供了一个简单的表单来上传文件(图像)。看起来像这样:
public IActionResult Process()
{
return View();
}
[HttpPost]
public IActionResult Process(List<IFormFile> files)
{
var telemetry = new TelemetryClient();
try
{
var result = files.Count + " file(s) processed " + Environment.NewLine;
foreach (var file in files)
{
result += file.FileName + Environment.NewLine;
var memoryStream = new MemoryStream();
file.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var binaryReader = new BinaryReader(memoryStream);
var bytes = binaryReader.ReadBytes((int)memoryStream.Length);
var imageInformation = ImageService.ProcessImage(bytes);
ImageService.SaveImage(imageInformation.Result, bytes, file.FileName.Substring(file.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1));
}
return View((object)result);
}
catch (Exception ex)
{
telemetry.TrackException(ex);
throw;
}
}
应用程序中的此表单工作正常。问题是我想使用 Microsoft Flow 将进入 SharePoint 库的文件提交到上面定义的 Web 应用程序。
我有文件流设置,它 运行s 并且没有出错,但是当我查看 HTTP 操作结果的主体时,它说已处理 0 个文件并且没有完成任何事情。
我设置的流程是
- 创建文件 (SharePoint) 时(这是指向特定的文档库
- Http (Http),方法:Post,Uri(指向我的应用程序),正文:来自上述 SharePoint 步骤的文件内容。
正如我提到的,这是发布到站点,但不能以 ASP.NET 方法可以处理的方式传递文件,因此它不会处理任何内容。我怎样才能更改流程或 Post 方法,使其正常工作。
更新了新信息 我已经用一个非常小的图像试过了,所以我可以获得一些额外的请求信息。使用浏览器中的表单我尝试了这个并使用 Fiddler 获得以下请求原始结果:
POST https://os-gbsphotoretain.azurewebsites.net/Image/Process HTTP/1.1
Host: os-gbsphotoretain.azurewebsites.net
Connection: keep-alive
Content-Length: 924
Pragma: no-cache
Cache-Control: no-cache
Origin: https://os-gbsphotoretain.azurewebsites.net
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarySjQVgrsvAqJYXmST
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://os-gbsphotoretain.azurewebsites.net/Image/Process
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: _ga=GA1.3.955734319.1501514097; ai_user=UkqSf|2017-07-31T15:17:38.409Z; ARRAffinity=1628d46398b292eb2e3ba76b4b0f1eb1e30abd9bd1036d7a90b9c51f7baa2306; ai_session=/fPFh|1502738361594.15|1502738361594.15
------WebKitFormBoundarySjQVgrsvAqJYXmST
Content-Disposition: form-data; name="files"; filename="printer.jpg"
Content-Type: image/jpeg
JFIF ` ` C
$.' ",#(7),01444'9=82<.342 C
2!!22222222222222222222222222222222222222222222222222 "
} !1AQa "q2 #B R br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
w !1AQ aq"2 B #3R br
% &'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?
+X K 21 c Z ] ӥg v ; : P I f > m;] ֬u nm ` Q 1 P6 s 9 |b r| G
------WebKitFormBoundarySjQVgrsvAqJYXmST--
通过流处理相同的图像,我得到以下作为流中的正文:
{
"$content-type": "image/jpeg",
"$content": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAQABADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD1C9EMuqzGK1juS+3P7rccgc4yMYxjv1q/ol0I4bfTpQVniXaoyDuQHjoTg7ccGsDU7O+0+xEdoJfMUKiKE84MB/dJ5B9mzj6VneFtO1271qx1G+hubaGBjmCSUfMSMZZQNoxzgDnPfGKqcnypEJW1R//Z"
}
所以看起来流程正在提交为 JSON。我现在将尝试一些额外的处理作为测试,但如果有人知道我可以在 Web 应用程序中放入什么来处理这个问题,我将不胜感激。
我添加了一个新方法(见下文),当我 运行 它在本地传递 Flow 所说的字符串是正文时,它就起作用了。但是当我 运行 从流程中得到它时,我在 DeserializeObject 行中得到 value cannot be null 错误。如何获取 Flow 传入的信息。
[HttpPost]
public IActionResult ProcessJson(string json)
{
var telemetry = new TelemetryClient();
try
{
var result = "JSON processed " + Environment.NewLine;
var details = (dynamic)Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var content = (string) details["$content"];
var bytes = Convert.FromBase64String(content);
ProcessBytes(bytes, "jpeg");
return View("Process", result);
}
catch (Exception ex)
{
telemetry.TrackException(ex);
throw;
}
}
我也尝试过使用此签名的方法,但运气不佳,要么它以 null 形式出现
[HttpPost]
public IActionResult ProcessJson([FromBody]FlowFile file)
{
...
}
public class FlowFile
{
[JsonProperty(PropertyName = "$content-type")]
public string ContentType { get; set; }
[JsonProperty(PropertyName = "$content")]
public string Content { get; set; }
}
我添加了一些中间件,这样我就可以得到原始的 Request.Body,最终结果就是这样。我不确定这等同于什么。

�����JFIF��`�`�����C�		

 $.' ",#(7),01444'9=82<.342���C			

2!!22222222222222222222222222222222222222222222222222�����"��������������	
�������}�!1AQa"q2���#B��R��br�	
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�����������������������������������������������������������������������������������	
������w�!1AQaq"2�B����	#3R�br�
�%�&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�����������������������������������������������������������������������������?������+X�K�����21�c�Z��]�ӥg�v��;�:����������P����I�f�>���m;]�֬u�nm���`�Q�1�P6�s�9�|b�r|���G�
不使用 List<IFormFile>
参数,而是访问 HttpContext.Request
中的 Files
属性。
好吧,我有点不清楚文件是如何发送的:它是 json object 之前文件被转换为 base64 字符串还是文件内容? (htmlheaders为指标)
如果你有 json 理论你可以做:
var parsedFileContent = Newtonsoft.Json.JsonConvert.DeserializeObject<FlowFile>(json);
而不是
var details = (dynamic)Newtonsoft.Json.JsonConvert.DeserializeObject(json);
它应该有效,当且仅当 ;),你发布的内容是正确的
{
"$content-type": "image/jpeg",
"$content": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAQABADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD1C9EMuqzGK1juS+3P7rccgc4yMYxjv1q/ol0I4bfTpQVniXaoyDuQHjoTg7ccGsDU7O+0+xEdoJfMUKiKE84MB/dJ5B9mzj6VneFtO1271qx1G+hubaGBjmCSUfMSMZZQNoxzgDnPfGKqcnypEJW1R//Z"
}
只要确保 json 是单行字符串(确保没有像 \n 或类似的隐藏字符)
另一方面,在您的 Fidler 捕获中,您有:
Content-Type: multipart/form-data;
所以正确的方法是 IFormFile
所以提供的信息有点误导。您可以尝试传递更多的错误日志吗? "object reference not sent to an instance of an object error" 非常普遍,通常这些类型的错误会通过堆栈跟踪缩小范围。
我终于得到了这份工作。我需要做的是直接读取原始请求流,而该流就是图像。 Flow 所说的关于以 Base64 编码 JSON 字符串提交图像的所有内容都不正确。我无法将其绑定到任何参数或作为 Request.Form.Files,但我可以直接读取流并直接从中保存图像。