使用 axios 从 vue 上传 XML 文件到 asp .net core

Posted

技术标签:

【中文标题】使用 axios 从 vue 上传 XML 文件到 asp .net core【英文标题】:Upload a XML file from vue with axios to 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 对象,它就可以工作,但所有其他内容类型都被阻止 【参考方案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 为您完成!

【讨论】:

以上是关于使用 axios 从 vue 上传 XML 文件到 asp .net core的主要内容,如果未能解决你的问题,请参考以下文章

从 Axios 响应中解析 XML,推送到 Vue 数据数组

如何在 Vue 和 Laravel 中使用 axios 上传图像文件和数据对象?

使用 vue js 和 axios 上传多个文件

vue中element-ui 使用axios上传文件 组件

vue中element-ui 使用axios上传文件 组件

vue中element-ui 使用axios上传文件 组件