本來文件上傳是一個簡單而常用的功能,但是,由於剛剛接觸extjs,對extjs中的控件及其使用方法並不熟悉,導致本來一個很快就可以搞定的文件上傳問題,弄了將近兩天的時間。現將問題及解決辦法發出來,供有相同煩惱的博園參考。只是我第一次發文,如有不妥,望各位海涵。
問題描述:在文件上傳的時候,在ie浏覽器下,文件上傳成功以後返回response時,回調函數直接報錯:無法調用null或者空值的success屬性。
首先看下extjs的代碼:
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <link href="Content/Extjs/resources/css/ext-all.css" rel="stylesheet" /> <script src="Content/Extjs/ext-all-debug.js" type="text/javascript"></script> <script src="Content/Extjs/ext-lang-zh_CN.js" type="text/javascript"></script> <script type="text/javascript"> Ext.onReady(function() { var uploadForm = Ext.create('Ext.form.Panel', { width:400, height: 100, items: [ { xtype: 'filefield', fieldLabel: '文件上傳', labelWidth: 80, msgTarget: 'side', allowBlank: false, margin: '10,10,10,10', anchor: '100%', buttonText:'選擇文件' }], buttons:[ { text: '上傳', handler: function() { uploadForm.getForm().submit({ url: 'ExtFormSubmitAjax.ashx', params: { action: 'UploadFile' }, success: function(form, action) { var jsonResult = Ext.JSON.decode(action.response.responseText); if (jsonResult.success) { } Ext.Msg.alert('提示', jsonResult.Msg); } }); } }, { text: '取消', handler: function() { } }], buttonAlign:'center' }); var mainPanel = Ext.create('Ext.panel.Panel', { renderTo: 'layoutDiv', width: 400, height: 150, margin: '50,50,50,50', items: [uploadForm] }); }); </script> </head> <body> <div id="layoutDiv"></div> </body> </html>
這就是一個簡單的文件上傳的Extjs代碼,由於測試,寫的有些凌亂。當點擊上傳後,調用後台的文件上傳代碼:
public void UploadFile(HttpContext context) { try { HttpFileCollection fileList = context.Request.Files; if (fileList.Count > 0) { String fileName = fileList[0].FileName; //在ie浏覽器下需要截取文件名稱,因為獲取的是上傳文件的全路徑,其他浏覽器不需要截取 fileName = fileName.Substring(fileName.LastIndexOf("\\", StringComparison.Ordinal) + 1); String uploadFilePath = context.Server.MapPath("/upload"); String fileSavePath = uploadFilePath + "\\" + fileName; if (File.Exists(fileSavePath)) { File.Delete(fileSavePath); } fileList[0].SaveAs(fileSavePath); context.Response.Write("{success:true,Msg:\"文件上傳成功\"}"); } else { context.Response.Write("{success:false,Msg:\"請選擇一個需要上傳的文件\"}"); } } catch (Exception) { } }
按理說這樣就可以完成文件上傳的操作,但是,我的程序在ie上運行,就是報錯。一直提示在ext-all-debug.js中的這裡報錯:
onSuccess: function(response) { var form = this.form, success = true, result = this.processResponse(response); if (result !== true && !result.success) { if (result.errors) { form.markInvalid(result.errors); } this.failureType = Ext.form.action.Action.SERVER_INVALID; success = false; } form.afterAction(this, success); },
提示result為null,無法調用空值的success屬性。其實原因就是返回的response對象種的responseText的值被ie自動添加了一個<pre>標簽所致。
導致在 this.processResponse(response)時,沒有辦法將一個字符串解析成json格式,所以ext-all-debug.js的源碼中就會報錯。
要聲明的是,這段代碼在谷歌、火狐等其他浏覽器中沒有問題,我相信在一部分的ie中也沒有問題,可能碰到高版本ie才會出現這樣的奇葩問題。
其實知道了問題的所在,解決辦法就相對簡單了。我們只要在後台代碼返回json的時候,為response對象設置一個contentType屬性就可以了,代碼如下:
public void UploadFile(HttpContext context) { try { HttpFileCollection fileList = context.Request.Files; if (fileList.Count > 0) { String fileName = fileList[0].FileName; //在ie浏覽器下需要截取文件名稱,因為獲取的是上傳文件的全路徑,其他浏覽器不需要截取 fileName = fileName.Substring(fileName.LastIndexOf("\\", StringComparison.Ordinal) + 1); String uploadFilePath = context.Server.MapPath("/upload"); String fileSavePath = uploadFilePath + "\\" + fileName; if (File.Exists(fileSavePath)) { File.Delete(fileSavePath); } fileList[0].SaveAs(fileSavePath); context.Response.ContentType = "text/html"; context.Response.Write("{success:true,Msg:\"文件上傳成功\"}"); } else { context.Response.Write("{success:false,Msg:\"請選擇一個需要上傳的文件\"}"); } } catch (Exception) { } }
這樣就可以了,ie下就可以原樣輸出response對象的響應信息。希望對 遇到相同問題的博員有所幫助,晚安各位