AI智能
改变未来

jquery使用ajax

0202年了, jQuery可以继续梭哈…
记录一下jQuery使用ajax上传文件Post表单的操作

相关文档: jQuery官方ajax文档

上传文件

仅上传单个文件

前端jquery使用

FormData

构造请求数据

<!-- 防止点击提交按钮页面自动刷新, 所以设置 onsubmit=\"return false;\" --><form onsubmit=\"return false;\" method=\"post\" class=\"form-group\"><div><input type=\"file\" id=\"i-avatar\" name=\"image\" /></div><div class=\"mt-2\"><button class=\"btn btn-primary\" onclick=\"uploadImage()\">提交</button></div></form><script type=\"text/javascript\">function uploadImage() {const form = new FormData();form.append(\"file\", $(\"#i-avatar\").prop(\"files\")[0]);$.ajax({type: \"post\",url: \"/videos/image\",contentType: false,data: form,processData: false,success: function () {window.alert(\"success\");}});}</script>

后端Action:

[HttpPost(\"image\")]public async Task<IActionResult> UploadImage([FromForm] IFormFile file){using (var rs = file.OpenReadStream()){string path = Path.Combine(_webHostEnvironment.WebRootPath, \"upload\", \"images\", file.FileName);Directory.CreateDirectory(Path.GetDirectoryName(path));using (var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite)){await rs.CopyToAsync(fs);await fs.FlushAsync();}}return Ok();}

这里就是拿到文件流然后保存到

~/wwwroot/upload/image

文件夹下, 这里文件名直接使用了用户上传的文件名, 微软官方文档中不建议这么做, 因为可能会有安全问题

写好之后在浏览器中测试, 看一下最终发出的请求是什么样的

可以看到, 虽然我们再ajax函数中将contentType设置成了false, 但是浏览器自动为我们添上了

content-type: multipart/form-data; boundary=----WebKitFormBoundaryxZyRmmXUfCxJRX7A

, 一开始我手动设置了

contentType: multipart/form-data

, 这样肯定是不行的, 至于为什么, 因为没有设置

boundary

这个东西啊

简单总结一下ajax要注意的配置

dataType

, 表示期望服务器返回的类型, 这个不能乱填, 如果返回的格式是

json

则设置为

json

, 返回的是纯文字, 则设置为

text

, 这个属性还可以被设置为

xml

,

html

,

script

,

jsonp

, 如果不设置这个属性, 那么jQuery会根据响应的MIME来自动推断, 如果你不确定响应的格式, 那么就不要设置这个属性;

contentType

, 发送数据给服务器时, 指定的数据的格式, 注意, 一定要注意, 这个属性是有默认值的, 且默认值是

application/x-www-form-urlencoded; ciharset=UTF-8

, 如果服务器不接受这种类型的输入, 那么就会请求失败, 所以务必确认好再设置, 如果将这个属性设置为

false

, 那么jquery就不会在请求头的加入

content-type

processData

, 告诉jquery, 是否要将请求数据内容转换成

application/x-www-form-urlencoded

, 默认是

true

, 也就是说jquery会将ajax的data属性格式化成

application/x-www-form-urlencoded

这种数据格式, 关于Post请求的数据格式的问题, 可以看这篇博文, HTTP_POST请求的数据格式, 非常详细, 如果是上传文件的场景, 要将这个属性设置成

false

上传文件的同时, 再传一些其他 Key-Value 类型数据

在用户注册的场景下, 需要提交用户名, 密码和头像等信息, 头像往往是一个图片文件; 当然, 也可以先单独上传头像, 然后传图片的url给用户注册接口api, 但是, 我觉得更好的做法是直接把文件一起传给用户注册接口的api, 这个接口同时保存用户头像;

还是使用

FormData

对象来构造请求数据:

<form onsubmit=\"return false;\"><div><label>用户名:&nbsp;<inpu56ct type=\"text\" id=\"username\" name=\"username\" value=\"\" /></label></div><div><label>密码:&nbsp;<input type=\"password\" id=\"password\" name=\"password\" value=\"\" /></label></div><div><label>头像:&nbsp;<input type=\"file\" id=\"avatar\" name=\"avatar\" value=\"\" multiple/></label></div><div><button class=\"btn btn-primary\" onclick=\"registerUser()\">注册</button></div><div id=\"register-result\"></div></form><script type=\"text/javascript\">function registerUser() {const formData = new FormData();formData.set(\"username\", $(\"#username\").val());formData.set(\"password\", $(\"#password\").val());const files = $(\"#avatar\").prop(\"files\");if (files && files.length > 0)formData.set(\"avatar\", files[0]);// 如果有多个文件怎么办?//for (let i = 0; i < files.length; i++) {//    formData.set(i, files[i]);//}$.ajax({url: \"/user\",type: \"post\",processData: false,contentType: false,data: formData,success: function (result) {$(\"#register-result\").56ctext(JSON.stringify(result));}});}</script>

后台接收数据:

[HttpPost]public Task<IActionResult> Register([FromForm] IFormCollection form){return Task.FromResult<IActionResult>(Ok(form));}

测试看一下请求是什么样的

可以看到

content-type

依旧是

multipart/formdata; boundary...

这种, 但是, 如果我要在传图片的同时, 传一些其他数据数据或者复杂对象怎么办啊? 比如我后台定义这样的对象:

public class VideoTagDto{public string TagName { get; set; }public DateTime CreateDate { get; set; }}public class ActorDto{public string Name { get; set; }public string Sex { get; set; }public string Country { get; set; }public DateTime Birth { get; set; }}public class VideoDto{public string Name { get; set; }public DateTime PublishDate { get; set; }public IList<VideoTagDto> VideoTags { get; set; }public IList<ActorDto> Actors { get; set; }public IFormFile CoverImage { get; set; }public VideoDto(){VideoTags = nead1w List<VideoTagDto>();Actors = new List<ActorDto>();}}

前台有没有办法可以让后台接口接收到

VideoDto

呢?

VideoDto

里面包含了

IFormFile

类型

CoverImage

;

不好意思, 好像不太可以, 我尝试了希望使用

application/json

格式来上传文件和其他复杂对象, 不过浏览器的

File

对象没办法序列化成JSON格式; 所以只能先上传文件, 然后拿到文件的url, 再和其他数据一起上传

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » jquery使用ajax