保存本地文件时出现createObjectURL执行错误,求问题排查
解决TypeError: Failed to execute 'createObjectURL' on 'URL'问题
你遇到的这个错误通常是因为传给createObjectURL的参数不是有效的Blob对象,结合你的代码来看,主要有以下几个问题和修复方案:
1. 后端文件名解码错误
前端通过encodeURIComponent(fileName)编码了文件名,但后端直接用编码后的字符串去查找文件,这会导致找不到目标文件(实际文件名是未编码的原始名称),最终返回404或无效内容,前端拿到的Blob对象无效,触发错误。
修复后端代码:
在接收fileName参数后,先进行URL解码:
public HttpResponseMessage Open(int savInitId, string fileName) { // 解码前端传来的文件名 fileName = HttpUtility.UrlDecode(fileName); var fullPath = CommonService.ServerSharedDrivePath + savInitId.ToString(); DirectoryInfo di = new DirectoryInfo(fullPath); FileInfo[] files = di.GetFiles(fileName); if (files.Length > 0) { HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); try { var fileStream = files[0].Open(FileMode.Open, FileAccess.Read); response.Content = new StreamContent(fileStream); response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = fileName }; return response; } catch (Exception ex) { // 处理文件打开失败的情况,比如文件被占用 return new HttpResponseMessage(HttpStatusCode.InternalServerError); } } return new HttpResponseMessage(HttpStatusCode.NotFound); }
2. 前端增加Blob有效性校验
在调用createObjectURL前,先确认拿到的blob是有效的Blob对象,避免传入null/undefined或非Blob类型的值:
修复前端代码:
function openFile() { var fileName = $(this).closest(".file-box").find(".file-name").text(); var encodedFileName = encodeURIComponent(fileName); $(document.body).showLoaderWithText("Downloading File"); $.ajax({ url: "/Procurement/Open", method: "POST", data: JSON.stringify({ savInitId: mv.options.savInitId, fileName: encodedFileName }), contentType: "application/json", // 新增:指定请求内容类型为JSON xhrFields: { responseType: "blob" }, global: false, success: function (blob) { // 校验Blob有效性 if (!(blob instanceof Blob) || blob.size === 0) { $(document.body).resetLoader(); alert("下载失败:获取到无效文件内容"); return; } if (window.navigator && window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, fileName); } else { var a = document.createElement("a"); var url = window.URL.createObjectURL(blob); a.href = url; a.download = fileName; // 解决部分浏览器无法直接触发click的问题 document.body.appendChild(a); a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(url); } $(document.body).resetLoader(); }, error: function (jqXhr, ajaxSettings, thrownError) { $(document.body).resetLoader(); if (/^not found$/ig.test(thrownError)) { alert("文件不存在"); } else { alert("下载失败:" + thrownError); } }, complete: function () { // 这里的resetLoader可以移到success和error里,避免重复执行 } }); }
额外优化点
- 前端AJAX请求新增
contentType: "application/json",确保后端能正确解析JSON格式的请求体; - 前端创建a标签后先添加到DOM再触发click,避免部分浏览器(如Firefox)无法触发下载;
- 后端增加文件打开异常捕获,避免因文件被占用等情况导致返回无效响应;
- 前端error回调添加用户提示,方便排查问题。
内容的提问来源于stack exchange,提问作者Philly
相关产品推荐
相关产品推荐

