【问题标题】:Upload a XML file from vue with axios to asp .net core使用 axios 从 vue 上传 XML 文件到 asp .net core
【发布时间】:2020-08-10 07:24:11
【问题描述】:

我正在努力将带有 axios 的 xml 文件上传到我的 asp .net 服务器。我正在使用来自 vue 端的以下代码来获取一个 xml 文件,该文件正在工作,然后将其上传到我的服务器:

uploadXmlFile(file: any) {
    const rawFile = new XMLHttpRequest();
    rawFile.open('GET', file, false);
    rawFile.onreadystatechange = () => {
        if (rawFile.readyState === 4) {
            if (rawFile.status === 200 || rawFile.status === 0) {
                const allText = rawFile.responseText;

                axios.post(`${url}`, rawFile, {
                headers: {
                    'Content-Type': 'application/xml',
                    'Accept-Language': 'application/xml',
                },
                });
            }
        }
    };
    rawFile.send(null);
}

在 asp .net 端我得到了这个功能:

[HttpPost]
public IActionResult Post(object xml)
{
    // Do something with the xml
    ...
}

上传文件会导致代码 415:不支持的媒体类型。

我发现了一些将 xml 格式化程序添加到我的项目的建议,但没有用,而且我不想解析 xml 文件,我只想将文件保存到我的文件系统。

我尝试结合不同的媒体类型上传 rawFile 和解析的文本,例如text/plain、text/xml 和 application/xml

我也尝试添加接受语言

我还使用此函数头尝试了 microsoft 文档中建议的方法: public async Task<IActionResult> OnPostUploadAsync(List<IFormFile> files)

我尝试使用 Postman 进行调试,上传了一张简单的图片,但出现了同样的错误。

【问题讨论】:

  • 不要发送同步的XMLHttpRequests!
  • @AluanHaddad 是的,我知道,但这不应该是这里的问题,对吧?我的意思是我在上传之前获得了 xml 文件。一旦这些东西起作用了,我会改进它......
  • @TobiasW 您能否尝试再次执行脚本,但这次从浏览器的开发人员工具和网络选项卡上传屏幕截图。我主要想看看请求标头和正文。我认为请求或操作的参数类型(object)有错误。
  • @vchan 我不太确定如何使用浏览器开发工具上传图片。但是我也在用 Postman 进行调试,并尝试用 Postman 上传图像,这也不起作用并给了我同样的错误
  • @vchan 一旦我将我的正文更改为 json 对象,它就可以工作,但所有其他内容类型都被阻止

标签: javascript c# typescript vue.js asp.net-core


【解决方案1】:

如果你这样写后端,它总是会尝试将内容序列化为 JSON,因为默认的序列化器。如果您发送内容类型 XML,它将不知道如何将您的 XML 反序列化为对象。

这是我们通常处理文件上传的方式:

[HttpPost]
public async Task<IActionResult> ReceiveFileUpload(CancellationToken cancellationToken = default(CancellationToken))
{
    var contentType = Request.ContentType; // Or HttpContext.Request
    var stream = Request.Body; // Or HttpContext.Request
    // Process file stream in whatever way, e.g. XmlDocument.Load(stream);
}

这至少应该使它在例如邮递员。

您的 axios 客户端看起来几乎没问题,有几点需要注意:

  • 您可能想发帖alltext,而不是rawFile
  • 你应该删除'Accept-Language': 'application/xml'
  • 我们通常使用 FileReader 来获取文件,不太确定您在做什么以及是否正确。
            axios.post(url, content, {
                headers: {
                    "Content-Type": "application/xml"
                }
            })
<input type='file' accept='text/plain' onchange='openFile(event)'>

var openFile = function(event) {
    var input = event.target;
    var text = "";
    var reader = new FileReader();
    var onload = function(event) {
        text = reader.result;
        console.log(text);

    };

    reader.onload = onload;
    reader.readAsText(input.files[0]);

};

(https://codepen.io/mlasater9/pen/jqQdOM/)

【讨论】:

  • 您建议的服务器代码更改有效。但是缺少Request对象的声明,不是吗?
  • Request 应该始终在您的 ASP.NET 控制器中可用。您可以将流解析为您喜欢的任何结构,例如XmlDocument。你还需要别的吗?
  • 你说的是 ASP.NET 还是 ASP.NET CORE,这个问题是关于哪个?
  • ASP.NET 核心。你也可以试试HttpContext.Request 而不是Request
  • 我不太明白你的问题是什么,也许可以为它打开一个新问题?
【解决方案2】:

首先,关于您的Front-end,您需要发送allText 常量而不是rawFile。所以你的代码会是这样的:

axios.post(
    url,
    allText,
    {
        headers: {
            'Content-Type': 'application/xml'
        }
    }
)

现在对于您的Back-end,默认情况下ASP.NET core 无法识别xml。您需要转到位于应用程序根目录的文件 Startup.cs 和方法 ConfigureServices,您需要添加 services.AddXmlSerializerFormatters()。所以你的代码会是这样的:

services
    .AddMvc()
    .AddXmlSerializerFormatters()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); // this depends on your .net core version

您还必须为要解析的xml 创建一个类模型。例如,如果您有这样的xml

<document>
    <id>12345</id>
    <content>This is a Test</content>
    <author>vchan</author>
</document>

你应该有一个像下面这样的类模型

[XmlRoot(ElementName = "document", Namespace = "")]
public class DocumentDto
{
    [XmlElement(DataType = "string", ElementName = "id")]
    public string Id { get; set; }

    [XmlElement(DataType = "string", ElementName = "content")]
    public string Content { get; set; }

    [XmlElement(DataType = "string", ElementName = "author")]
    public string Author { get; set; }
}

另外,.net 可以自己理解原始的 xml 正文,因此,您的控制器的操作应该如下所示

[HttpPost]
public IActionResult TestMethod([FromBody] DocumentDto xml) {
    // Do something with the xml
}

请注意,您应该始终使用HTTP header Content-Type: application/xml 来处理您的请求,以便.net 能够理解、解析和反序列化它。您无需为要实施的每个不同操作重新发明轮子,.net 为您完成!

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 2017-06-12
    • 1970-01-01
    • 2021-09-09
    • 2020-04-09
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多