it-swarm.dev

باستخدام طريقة jQuery's ajax لاسترداد الصور كنقط

لقد طرحت مؤخرًا سؤالًا آخر (متعلق) ، والذي يؤدي إلى سؤال المتابعة هذا: تقديم البيانات بدلاً من ملف لنموذج إدخال

من خلال قراءة وثائق jQuery.ajax () ( http://api.jquery.com/jQuery.ajax/ ) ، يبدو أن قائمة أنواع البيانات المقبولة لا تتضمن الصور.

أحاول استرداد صورة باستخدام jQuery.get (أو jQuery.ajax إذا كنت مضطرًا لذلك) ، قم بتخزين هذه الصورة في Blob وتحميلها إلى خادم آخر في طلب POST. في الوقت الحالي ، يبدو الأمر بسبب عدم التطابق في أنواع البيانات ، وينتهي الأمر إلى تلف صوري (حجم عدم تطابق البايت ، وما إلى ذلك).

التعليمة البرمجية لتنفيذ هذا هي كما يلي (في coffeescript ولكن يجب ألا يكون من الصعب تحليل):

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)

كيف يمكنني استرجاع هذه الصورة كبقعة بدلا من ذلك؟

60
jabalsad

لا يمكنك القيام بذلك باستخدام jQuery ajax ، ولكن باستخدام XMLHttpRequest الأصلي.

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();      

تصحيح

لذا ، فبإعادة النظر في هذا الموضوع ، يبدو أنه من الممكن فعل ذلك مع 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%>

أو

استخدم xhrFields لتعيين 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%>
108
Musa

شكرًا جزيلاً علىMusa وهنا دالة أنيقة تقوم بتحويل البيانات إلى سلسلة base64. قد يكون هذا في متناول يديك عند التعامل مع ملف ثنائي (pdf ، png ، jpeg ، docx ، ...) في WebView يحصل على الملف الثنائي ولكن تحتاج إلى نقل بيانات الملف بأمان إلى التطبيق الخاص بك.

// 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);
}
3
mxl

إذا كنت بحاجة إلى معالجة رسائل الخطأ usingjQuery.AJAXستحتاج إلى تعديل وظيفة xhr حتى لا يتم تعديل responseType عندما يكون خطأ يحدث.

لذلك سيكون عليك تعديل responseType إلى "blob" فقط إذا كانت مكالمة ناجحة:

$.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) {
        console.error(xhr.responseText); //Here you are able now to access to the property responseText as you have the type set to text instead of blob.
    },
    success: function(data) {
        console.log(data); //Here is blob type
    }
});

ملاحظة: إذا قمت بتصحيح وضع نقطة توقف عند النقطة مباشرةً بعد تعيين xhr.responseType إلى "blob" ، يمكنك ملاحظة أنه إذا حاولت الحصول على قيمة "responseText" ، فستحصل على الرسالة التالية :

لا يمكن الوصول إلى القيمة إلا إذا كان "responseType" الخاص بالكائن هو "" أو "text" (كان "blob").

1
Alberto