Estoy trabajando en un fragmento de código usando la API Stripe Connect donde el usuario puede enviar una imagen desde un input type="file" a una llamada AJAX a través de jQuery, de esta manera:
var form_file = new FormData(); form_file.append('file', document.querySelector('input#file_to_send').files[0]); Cuando el usuario envía el formulario, copio la imagen en una carpeta en mi servidor a través de PHP y mantengo su nombre en una variable de sesión. Si algo es incorrecto o falta en el formulario, el usuario vuelve a la misma página, donde la imagen se muestra en un elemento img debajo del input type="file" , para que el usuario sepa que su imagen se ha tenido en cuenta. .
Después de eso, necesito enviar el archivo en una llamada AJAX nuevamente ... Excepto que esta vez, el archivo ya no se puede seleccionar desde el input type="file" , la única fuente accesible que tengo sería tomar su nombre del elemento img en JavaScript.
Ahora, si hago esto:
var form_file = new FormData(); form_file.append('file', $('img#visual').attr('src'));Y envíe esto a través de la misma llamada AJAX:
$.ajax({ url: 'https://uploads.stripe.com/v1/files', type: 'POST', processData: false, contentType: false, headers: {'Authorization': 'Bearer xxxxxxxxxxxxxxxxx' }, data: form_file }).fail(function(e) { console.log('fail: ' + e); }).done(function(e) { console.log('file uploaded: ' + e.id); }); Mi pregunta, lo adivinó, es: ¿hay alguna manera de/cómo debo hacer para enviar un archivo no desde un elemento de input como fuente, sino una ruta definida tomada desde un elemento img ?
Leí tu pregunta por segunda vez. Si entiendo correctamente, debe enviar una solicitud AJAX de dominio cruzado a stripe.com, por lo que no está controlando el código PHP en el lado del servidor, ¿verdad?
RESPUESTA CORTA:
La forma más fácil sería verificar su formulario en Javascript en lugar de PHP, por lo que no tendrá que volver atrás y "perder" el archivo de entrada seleccionado.
... PERO si realmente necesita/quiere enviar un archivo entre dominios usando solo su URL ,
luego deberá convertir el URI de datos en archivo y luego agregarlo a FormData :
1/ Obtén el valor base64 de tu imagen
function toDataUrl(url, callback) { var xhr = new XMLHttpRequest(); xhr.onload = function() { var reader = new FileReader(); reader.onloadend = function() { callback(reader.result); } reader.readAsDataURL(xhr.response); }; xhr.open('GET', url); xhr.responseType = 'blob'; xhr.send(); }2/ Convierte la imagen base64 a Blob:
function DataURIToBlob(dataURI: string) { const splitDataURI = dataURI.split(',') const byteString = splitDataURI[0].indexOf('base64') >= 0 ? atob(splitDataURI[1]) : decodeURI(splitDataURI[1]) const mimeString = splitDataURI[0].split(':')[1].split(';')[0] const ia = new Uint8Array(byteString.length) for (let i = 0; i < byteString.length; i++) ia[i] = byteString.charCodeAt(i) return new Blob([ia], { type: mimeString }) }3/ Enviarle Blob con FormData:
const file = DataURIToBlob(imgBase64) const formData = new FormData(); formData.append('upload', file, 'image.jpg')Fuentes:
Editar:
Puede acelerar las fases 1 y 2 utilizando la API Fetch para obtener la imagen Blob directamente.
(ADVERTENCIA: no compatible con IE)
Fuente: ¿Cómo obtener un archivo () o un blob () de una URL en javascript?
¡Gracias @e-telier! Después de combinar sus muestras de código con lo que hay en los enlaces que sugirió, ¡pude lograr lo que quería! Aquí está el código con el que terminé:
var visual_source = 'upload/file-source.png'; var visual_ext = visual_source.split('.').pop(); var visual = await fetch(visual_source); console.log(visual); var visual_as_blob = await visual.blob(); console.log(visual_as_blob); var visual_as_file = new File([visual_as_blob], 'file-name-renamed.' + visual_ext, { lastModified: new Date().getTime(), type: visual_as_blob.type }); console.log(visual_as_file); form_file.append('file', visual_as_file);Agregué un archivo console.log() en cada paso de esto si alguien necesita este código y quiere ver el resultado de lo que está sucediendo paso a paso. Siendo los pasos:
Después de eso, se puede enviar a través de ajax a la API de Stripe.
¡¡De nuevo, gracias por tu ayuda!! :))