Sử dụng phương thức ajax của jQuery để truy xuất hình ảnh dưới dạng một đốm màu


84

Gần đây tôi đã hỏi một câu hỏi khác (có liên quan), dẫn đến câu hỏi tiếp theo này: Gửi dữ liệu thay vì tệp cho biểu mẫu đầu vào

Đọc qua tài liệu jQuery.ajax () ( http://api.jquery.com/jQuery.ajax/ ), có vẻ như danh sách dataTypes được chấp nhận không bao gồm hình ảnh.

Tôi đang cố gắng truy xuất hình ảnh bằng jQuery.get (hoặc jQuery.ajax nếu phải), lưu trữ hình ảnh này trong Blob và tải nó lên máy chủ khác theo yêu cầu ĐĂNG. Hiện tại, có vẻ như do kiểu dữ liệu không khớp, hình ảnh của tôi cuối cùng bị hỏng (kích thước tính bằng byte không khớp, v.v.).

Mã để thực hiện điều này như sau (nó nằm trong coffeescript nhưng không khó để phân tích cú pháp):

handler = (data,status) ->
  fd = new FormData
  fd.append("file", new Blob([data], { "type" : "image/png" }))
  jQuery.ajax {
    url: target_url,
    data: fd,
    processData: false,
    contentType: "multipart/form-data",
    type: "POST",
    complete: (xhr,status) ->
      console.log xhr.status
      console.log xhr.statusCode
      console.log xhr.responseText

  }
jQuery.get(image_source_url, null, handler)

Làm cách nào để truy xuất hình ảnh này dưới dạng một đốm màu?


Tôi nghĩ bạn phải thay đổi kiểu phản hồi ở phía máy chủ.
Eric Frick

Tôi đang cố gắng lấy một hình ảnh từ bất kỳ url nào, không phải máy chủ mà tôi nhất thiết phải sở hữu.
jabalsad


Có vẻ như ba giải pháp trong câu trả lời đó là (1) sử dụng thẻ <img>, (2) làm cho máy chủ phân phát hình ảnh dưới dạng mã hóa byte64 hoặc (3) sử dụng bộ nhớ cache của trình duyệt. (2) bị loại trừ vì tôi muốn tập lệnh hoạt động với bất kỳ url hình ảnh nào. Tôi không chắc làm thế nào để sử dụng (1) hoặc (3) vì khi tôi đã tải xuống hình ảnh, tôi cần chuyển đổi nó thành Blob.
jabalsad

tùy chọn 3 sẽ chỉ hoạt động nếu bạn đã tải xuống hình ảnh. Lần đầu tiên bạn sẽ cần một cái gì đó khác biệt. Có thể chọn 1?
Eric Frick

Câu trả lời:


146

Bạn không thể làm điều này với jQuery ajax, nhưng với XMLHttpRequest nguyên bản.

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if (this.readyState == 4 && this.status == 200){
        //this.response is what you're looking for
        handler(this.response);
        console.log(this.response, typeof this.response);
        var img = document.getElementById('img');
        var url = window.URL || window.webkitURL;
        img.src = url.createObjectURL(this.response);
    }
}
xhr.open('GET', 'http://jsfiddle.net/img/logo.png');
xhr.responseType = 'blob';
xhr.send();      

BIÊN TẬP

Vì vậy, xem lại chủ đề này, có vẻ như thực sự có thể làm điều này với jQuery 3

jQuery.ajax({
        url:'https://images.unsplash.com/photo-1465101108990-e5eac17cf76d?ixlib=rb-0.3.5&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ%3D%3D&s=471ae675a6140db97fea32b55781479e',
        cache:false,
        xhr:function(){// Seems like the only way to get access to the xhr object
            var xhr = new XMLHttpRequest();
            xhr.responseType= 'blob'
            return xhr;
        },
        success: function(data){
            var img = document.getElementById('img');
            var url = window.URL || window.webkitURL;
            img.src = url.createObjectURL(data);
        },
        error:function(){
            
        }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<img id="img" width=100%>

hoặc là

sử dụng xhrFields để đặt responseType

    jQuery.ajax({
            url:'https://images.unsplash.com/photo-1465101108990-e5eac17cf76d?ixlib=rb-0.3.5&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ%3D%3D&s=471ae675a6140db97fea32b55781479e',
            cache:false,
            xhrFields:{
                responseType: 'blob'
            },
            success: function(data){
                var img = document.getElementById('img');
                var url = window.URL || window.webkitURL;
                img.src = url.createObjectURL(data);
            },
            error:function(){
                
            }
        });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
    <img id="img" width=100%>


Cảm ơn. Tôi chỉ tìm ra nó và thấy câu trả lời của bạn. Nó tương tự như của tôi (khác với thực tế là tôi đăng nó lên một biểu mẫu thay vì đặt nó trên một đối tượng <img>). Tôi sẽ đánh dấu nó như nào đúng :)
jabalsad

@jabalsad câu hỏi được hỏi How can I retrieve this image as a blob instead?, dù sao đó chỉ là để demo nó, handlersẽ lấy this.responsevà thêm nó vào một đối tượng formdata và gửi nó qua ajax.
Musa

2
+1, hoạt động tuyệt vời! Và FYI, điều này có thể cuối cùng được thêm vào jQuery sớm: github.com/jquery/jquery/pull/1525
lambshaanxy

9
2017: jQuery vẫn không thể xử lý loại 'blob'?
robsch

1
'xhrFields' cũng hoạt động trong jQuery 2 (được thử nghiệm trong 2.2.4)
Bampfer

15

Nếu bạn cần xử lý thông báo lỗi bằng jQuery.AJAX, bạn sẽ cần phải sửa đổi xhrhàm để hàmresponseType không bị sửa đổi khi xảy ra lỗi.

Vì vậy, bạn sẽ phải sửa đổi responseTypethành " blob " chỉ khi đó là một cuộc gọi thành công:

$.ajax({
    ...
    xhr: function() {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 2) {
                if (xhr.status == 200) {
                    xhr.responseType = "blob";
                } else {
                    xhr.responseType = "text";
                }
            }
        };
        return xhr;
    },
    ...
    error: function(xhr, textStatus, errorThrown) {
        // Here you are able now to access to the property "responseText"
        // as you have the type set to "text" instead of "blob".
        console.error(xhr.responseText);
    },
    success: function(data) {
        console.log(data); // Here is "blob" type
    }
});

Ghi chú

Nếu bạn gỡ lỗi và đặt một điểm ngắt tại điểm ngay sau khi đặt xhr.responseTypethành " blob ", bạn có thể lưu ý rằng nếu bạn cố gắng lấy giá trị cho responseTextbạn sẽ nhận được thông báo sau:

Giá trị chỉ có thể truy cập được nếu 'responseType' của đối tượng là '' hoặc 'văn bản' (là 'blob').


1
Cảm ơn rât nhiều! Đây là giải pháp tôi đang tìm kiếm. Tôi cần AJAX để xử lý phản hồi thành công dưới dạng "blob" (kho lưu trữ ZIP trong trường hợp của tôi) trong .done()phương thức và nếu có sự cố, phản hồi trong .fail()phương thức phải được xử lý dưới dạng "văn bản", vì nếu không thì responseTextlà trống, v.v. Điều này giải pháp làm việc hoàn hảo cho tôi!
Informatik01

4

Xin gửi lời cảm ơn sâu sắc đến @Musa và đây là một hàm gọn gàng giúp chuyển đổi dữ liệu thành chuỗi base64. Điều này có thể hữu ích cho bạn khi xử lý tệp nhị phân (pdf, png, jpeg, docx, ...) trong WebView nhận được tệp nhị phân nhưng bạn cần chuyển dữ liệu của tệp một cách an toàn vào ứng dụng của mình.

// runs a get/post on url with post variables, where:
// url ... your url
// post ... {'key1':'value1', 'key2':'value2', ...}
//          set to null if you need a GET instead of POST req
// done ... function(t) called when request returns
function getFile(url, post, done)
{
   var postEnc, method;
   if (post == null)
   {
      postEnc = '';
      method = 'GET';
   }
   else
   {
      method = 'POST';
      postEnc = new FormData();
      for(var i in post)
         postEnc.append(i, post[i]);
   }
   var xhr = new XMLHttpRequest();
   xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200)
      {
         var res = this.response;
         var reader = new window.FileReader();
         reader.readAsDataURL(res); 
         reader.onloadend = function() { done(reader.result.split('base64,')[1]); }
      }
   }
   xhr.open(method, url);
   xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
   xhr.send('fname=Henry&lname=Ford');
   xhr.responseType = 'blob';
   xhr.send(postEnc);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.