2013-07-17 21 views
6

Tôi hiện đang nâng cấp các phần của trang web ASP.NET MVC để có nhiều RESTful hơn, sử dụng ASP.NET Web API. Một trong những tính năng chúng tôi đang chuyển sang thiết kế RESTful hơn là tải lên tệp. Đối với khách hàng, chúng tôi đang sử dụng plugin jquery, ajaxForm, để bao bọc việc tạo khung nội tuyến sẽ gửi biểu mẫu chứa phần tử đầu vào tệp. Điều này đã làm việc tuyệt vời với ASP.NET MVC.Khung nội tuyến IE không xử lý phản hồi ứng dụng/json đúng cách

Khi thay đổi nó để sử dụng điểm cuối API Web của chúng tôi, trả về phản hồi với Loại nội dung "ứng dụng/json", chúng tôi đã nhận thấy sự cố với Internet Explorer 9. Có vẻ như hàm thành công ajaxForm không bao giờ được gọi. Từ những gì tôi có thể nói, có vẻ như khung nội tuyến trong IE diễn giải nội dung của phản hồi với Content-Type là "application/json" dưới dạng tệp đính kèm sẽ được tải xuống. Điều này có nghĩa là nó không bao giờ kích hoạt sự kiện "nạp" của iframe, điều đó có nghĩa là trình xử lý sự kiện onjaxForm onload sẽ không bao giờ được kích hoạt, và hàm thành công ajaxForm của chúng ta sẽ không bao giờ được gọi.

Chúng tôi cũng nhận thấy sự cố trong IE 7 nhưng chúng tôi không thể tạo lại sự cố trong phiên bản Firefox hoặc Chrome mới nhất, ngay cả khi buộc họ sử dụng iframe thay vì API tệp có FormData.

Để giải quyết vấn đề này ngay bây giờ, tôi bây giờ buộc trả lời kiểu nội dung trở lại "văn bản/đồng bằng", đó là những gì chúng tôi đã quay trở lại trước đó từ hành động điều khiển ASP.NET MVC xử lý tệp tải lên. Điều này làm cho mọi thứ hoạt động trở lại.

Câu hỏi của tôi:

  • Có cách nào tôi có thể giữ cho Web API phản ứng Content-Type là "application/json" và đã IE giải thích nó một cách chính xác?
  • Có cách nào tốt hơn để thực hiện tải lên tệp khi sử dụng IE và API Web không? Có lẽ một plugin khác hoặc kỹ thuật tốt hơn?

Hạn chế bổ sung: Tôi không thể sử dụng ActiveX hoặc Flash cho trang web này. Tôi có thể sử dụng một plugin khác, nhưng chỉ khi nó có hỗ trợ đa trình duyệt chung. (IE, Chrome, Firefox, Safari, vv)

HTML của tôi:

<form id="uploadFormId" action="" method="post" enctype="multipart/form-data" encoding="multipart/form-data"> 
    <input type="file" name="files[]"/> 
</form> 

javascript của tôi:

function onFileChange(e) { 
    if (e.type === e.originalEvent.type) { 
     var filePath = $(e.currentTarget).val(); 
     if (filePath !== '') { 
      $(this).closest('form').submit(); 
     } 
    } 
}; 

$(function() { 
    $('#uploadFormId').ajaxForm({ 
     url: "api/Files/1234", 
     dataType: 'json', 
     success: function (response) { 
      alert(response); 
     }, 
     error: function (xhr, status, error) { 
      alert(status); 
     } 
    }); 
    $('#uploadFormId input[type="file"]').bind('change', onFileChange); 
}); 

"application/json" tiêu đề phản ứng (không làm việc trong IE) :

Cache-Control:no-cache 
Content-Length:337 
Content-Type:application/json; charset=utf-8 
Date:Wed, 17 Jul 2013 13:10:47 GMT 
Expires:-1 
Pragma:no-cache 
Server:Microsoft-IIS/8.0 
X-AspNet-Version:4.0.30319 
X-Powered-By:ASP.NET 

"text/plain" tiêu đề phản ứng (hoạt động trong IE):

Cache-Control:no-cache 
Content-Length:322 
Content-Type:text/plain 
Date:Wed, 17 Jul 2013 13:17:24 GMT 
Expires:-1 
Pragma:no-cache 
Server:Microsoft-IIS/8.0 
X-AspNet-Version:4.0.30319 
X-Powered-By:ASP.NET 

Trả lời

9

Khi ajaxForm sử dụng chế độ gửi khung nội tuyến, phản hồi từ cuộc gọi nhất thiết phải được hiển thị trong phần thân của khung nội tuyến. Điều này có nghĩa là nó phải là một kiểu nội dung mà trình duyệt có thể hiển thị — thường là HTML, nhưng text/plain cũng sẽ hoạt động. Tuy nhiên, trình duyệt không thể hiển thị application/json làm trang.

Có một vấn đề cụ thể khi sử dụng text/plain, trong đó trình duyệt có thể xem xét nội dung và xử lý tài nguyên dưới dạng HTML nếu có gì đó giống như thẻ HTML trong dữ liệu. Nếu JSON của bạn trở lại với dữ liệu do người dùng cung cấp, điều đó có thể cho phép ai đó tiêm JavaScript thực thi vào trang web của bạn (tấn công XSS).

Theo đề nghị của các ajaxForm doc bạn đang mong đợi để phát hiện khi cuộc gọi đến từ một bài iframe thay vì AJAX, và trả về một phản ứng text/html với một wrapper textarea trong trường hợp đó:

Để giải thích cho sự thách thức của kịch bản và phản hồi JSON khi sử dụng chế độ khung nội tuyến, Plugin biểu mẫu cho phép các phản hồi này được nhúng vào phần tử văn bản và bạn nên làm như vậy cho các loại phản hồi này khi được sử dụng trong kết hợp với tải lên tệp và trình duyệt cũ hơn.

+0

Đối với câu hỏi "Tại sao IE9 + hoạt động theo cách này": Xử lý ứng dụng/json dưới dạng loại tệp thích hợp (dẫn đến tải xuống tệp thay vì ngửi sang một số định dạng khác) là bản sửa lỗi bảo mật dành cho IE9. – EricLaw