我已经被困在这几个小时了,甚至谷歌都不能帮助了。我正在尝试使用xmlhttprequest将文件从客户端发送到后端。我无法获得C#端的文件名,类型或内容。我很感激这方面的帮助。我遇到的很多代码都有我在ASP.Net 5和MVC 6中不支持的方法(例如HttpContext.Current和HttpPostedFile)
这是我的客户端JavaScript请求。这会发送绑定到我的模型的查询字符串没有问题,因此很容易访问,但是获取文件是我遇到的问题。
var form = new FormData();
form.append("file", file);
var queryParams = "id=" + (id == null ? -1 : id);
queryParams += "&name=" + name;
queryParams += "&value=" + val;
xhrAttach(REST_DATA + "/attach?" + queryParams, form, function (item) {
console.log('attached: ', item);
alert(item.responseText);
row.setAttribute('data-id', item.id);
removeProgressIndicator(row);
setRowContent(item, row);
}, function (err) {
console.log(err);
//stop showing loading message
stopLoadingMessage();
document.getElementById('errorDiv').innerHTML = err;
});
function xhrAttach(url, data, callback, errback)
{
var xhr = new createXHR();
xhr.open("POST", url, true);
//xhr.setRequestHeader("Content-type", "multipart/form-data");
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
callback(parseJson(xhr.responseText));
}else{
errback("Error: "+xhr.responseText);
}
}
};
xhr.timeout = 1000000;
xhr.ontimeout = errback;
xhr.send(data);
}
这是我的Controller处理请求。附件是一个模型,查询字符串绑定到它没有问题。我无法找到如何将File参数添加到模型中,或者这甚至是否重要。我尝试的东西都在这个代码下。
// POST: /api/db/attach
[Route("/api/[controller]/attach")]
[HttpPost]
public async Task<dynamic> attach(Attachment attachment)
{
//get the file somehow
}
我已经尝试了很多东西,但是不记得究竟是什么,这是我尝试过的一件事,但是没有用。
var file = Request.Form["file"];
这是附件模型以防万一
namespace MyModel.Models
{
public class Attachment
{
public long id { get; set; }
public string name { get; set; }
public string value { get; set; }
}
}
答案 0 :(得分:0)
我建议尝试以下方法:
public async Task<dynamic> attach([FromURI]Attachment attachment, [FromBody] FormDataCollection formData)
然后FormDataCollection应该有用于检索的表单数据。
答案 1 :(得分:0)
将一个名为File
的公共get / set属性添加到Attachment
模型中,并将上传的文件绑定到此属性。
public class Book
{
public string Name { get; set; }
public IFormFile File { get; set; }
}
以下控制器提供了模型绑定上传文件的不同方式的示例。 https://github.com/aspnet/Mvc/blob/9f9dcbe6ec2e34d8a0dfae283cb5e40d8b94fdb7/test/WebSites/ModelBindingWebSite/Controllers/FileUploadController.cs#L81
public KeyValuePair<string, FileDetails> UploadModelWithFile(Book book)
{
var file = book.File;
var reader = new StreamReader(file.OpenReadStream());
var fileContent = reader.ReadToEnd();
var parsedContentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
var fileDetails = new FileDetails
{
Filename = parsedContentDisposition.FileName,
Content = fileContent
};
return new KeyValuePair<string, FileDetails>(book.Name, fileDetails);
}
如果这不起作用,那么我怀疑你的请求格式不正确。
答案 2 :(得分:0)
如果要在MVC端使用模型,请不要使用查询参数或FormData。只是不要。对我来说,最好先将文件放入base64字符串,而不是尝试发送File对象本身。我发布了有关如何执行此操作的信息:Convert input=file to byte array
然后,声明并格式化JSON对象:
var dataObj = {
file = fileByteArray[0],
id = (id == null ? -1 : id),
name = name,
value = val
};
fileByteArray[0]
正在引用我链接中的对象。我在那里的答案假设您只是将文件base64字符串加载到该全局数组对象中。您可以将它保存为数组,就像我一样,然后逐个循环遍历它们,将[0]
替换为[i]
,例如,作为for
循环中的索引器,或者只使用var fileByteArray = ""
与其他代码一起使用,使其不会推送其他文件,但总是只覆盖该变量,&amp;只是使用它。
关于最后一个参数的注意事项 - 如果使用jQuery,请不要使用val
- 这是一个关键字。我上面只有它,因为它是你传递给URL参数值的。
摆脱这一行中的queryParams
:
xhrAttach(REST_DATA + "/attach?" + queryParams, form, function (item) {
将其更改为:
xhrAttach(REST_DATA + "/attach", form, function (item) {
将内容类型设置为:
,将注释掉的位置设置为xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
更改您发送的内容 - 它不再是FormData,它是JSON对象,需要进行字符串化处理:
xhr.send(JSON.stringify(dataObj));
修复您的模型,现在包括文件base64 string:
public class Attachment
{
public string file { get; set; }
public long id { get; set; }
public string name { get; set; }
public string value { get; set; }
}
修复你的POST方法。 2个问题:
[HttpPost]
,则无法使用ApiController
,您可能应该这样做。它必须是[System.Web.Http.HttpPost]
,是的,它必须完全拼写出来,或者它会假设它是[System.Web.Mvc.HttpPost]
而不是分配路线 - 当你尝试时会出现404 - Not Found
错误做你的POST。如果您继承自Controller
,请忽略此。如果您继承自[FromBody]
,则需要在模型上添加ApiController
代码:
public async Task<dynamic> attach([FromBody]Attachment attachment) { ... }
然后你得到这样的文件:
string base64FileString = attachment.file;
如果要将其存储在数据库的byte[]
中,可以将其转换为:
byte[] bytes = System.Convert.FromBase64String(base64FileString);
顺便说一句,我认为您的回复处理是错误的。我不会这样做:
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
callback(parseJson(xhr.responseText));
}else{
errback("Error: "+xhr.responseText);
}
}
};
我就是这样做的:
xhr.onreadystatechange = function(response){
if(xhr.readyState == 4 && xhr.status == 200){
callback(parseJson(response.target.responseText));
} else {
alert("Error: " + response.target.responseText);
}
};
假设response.target.responseText
以可以显示的方式从服务器端发回错误。如果没有,将它发送到可以解析它的功能将是正确的选择。我不认为xhr.responseText
是正确的。