Recientemente hice otra pregunta (relacionada), que llevó a esta pregunta de seguimiento: Enviar datos en lugar de un archivo para un formulario de entrada
Al leer la documentación de jQuery.ajax () ( http://api.jquery.com/jQuery.ajax/ ), parece que la lista de tipos de datos aceptados no incluye imágenes.
Estoy tratando de recuperar una imagen usando jQuery.get (o jQuery.ajax si tengo que hacerlo), almacenar esta imagen en un Blob y subirla a otro servidor en una solicitud POST. Actualmente, parece que debido a la falta de coincidencia en los tipos de datos, mis imágenes terminan siendo corruptas (tamaño en bytes no coinciden, etc.).
El código para realizar esto es el siguiente (está en coffeescript pero no debería ser difícil de analizar):
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)
¿Cómo puedo recuperar esta imagen como un blob?
fuente
Respuestas:
No puede hacer esto con jQuery ajax, pero con XMLHttpRequest nativo.
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();
EDITAR
Entonces, revisando este tema, parece que de hecho es posible hacer esto con 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%>
o
use xhrFields para establecer el 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%>
fuente
How can I retrieve this image as a blob instead?
, de todos modos, fue solo para una demostración, lahandler
tomaráthis.response
y agregará a un objeto formdata y lo enviará a través de ajax.Si necesita manejar mensajes de error usando jQuery.AJAX , deberá modificar la
xhr
función pararesponseType
que no se modifique cuando ocurra un error.Por lo tanto, tendrá que modificar
responseType
a " blob " solo si es una llamada exitosa:$.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 } });
Nota
Si depura y coloca un punto de interrupción en el punto justo después de establecer el
xhr.responseType
" blob ", puede tener en cuenta que si intenta obtener el valorresponseText
, obtendrá el siguiente mensaje:fuente
.done()
método, y si algo salía mal, la respuesta en el.fail()
método debería manejarse como "texto", porque de lo contrarioresponseText
estaba vacío, etc. ¡La solución funcionó perfectamente para mí!Un gran agradecimiento a @Musa y aquí hay una función ordenada que convierte los datos a una cadena base64. Esto puede resultarle útil cuando maneje un archivo binario (pdf, png, jpeg, docx, ...) en un WebView que obtiene el archivo binario, pero necesita transferir los datos del archivo de forma segura a su aplicación.
// 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); }
fuente