Necesito PONER un archivo de imagen de la aplicación nativa de reacción en una URL de carga s3 preconfigurada. Vi un ejemplo con fetch que carga la imagen como una ruta binaria a través de la ruta, pero lo hace como una carga de formulario de varias partes. Debido a que la URL de carga de s3 solo puede tomarlo como un binario sin procesar en el cuerpo, y no como un tipo de contenido de varias partes, ¿cuál es la sintaxis para PONER la imagen binaria sin procesar como el cuerpo usando fetch o cualquier otra biblioteca en reaccionar nativo ?
El siguiente código lo carga como datos de formulario, que no es lo que quiero hacer.
var photo = { uri: response.uri, name: fileName, }; const body = new FormData(); // how can I do this not as a form? body.append('photo', photo); const results = await fetch('https://somes3uploadurl.com, { method: 'PUT', body, });Resulta que puede enviar el archivo de varias maneras, incluido base64 y como Buffer .
Usando react-native-fs y buffer :
La carga como base64 funcionó, pero la imagen se dañó de alguna manera. Así que subí usando un búfer:
export const uploadToAws = async (signedRequest, file) => { const base64 = await fs.readFile(file.uri, 'base64') const buffer = Buffer.from(base64, 'base64') return fetch(signedRequest, { method: 'PUT', headers: { 'Content-Type': 'image/jpeg; charset=utf-8', 'x-amz-acl': 'public-read', }, body: buffer, }) } Tenga en cuenta que en el servidor, debe asegurarse de configurar el tipo de contenido correcto: { ContentType: "image/jpeg; charset=utf-8", 'x-amz-acl': 'public-read' } como parece que fetch agrega el juego de caracteres a Content-Type.
También puede usar la siguiente solución:
/** * @param {{contentType: string, uploadUrl: string}} resourceData for upload your image * @param {string} file path to file in filesystem * @returns {boolean} true if data uploaded */ async uploadImage(resourceData, file) { return new Promise((resolver, rejecter) => { const xhr = new XMLHttpRequest(); xhr.onload = () => { if (xhr.status < 400) { resolver(true) } else { const error = new Error(xhr.response); rejecter(error) } }; xhr.onerror = (error) => { rejecter(error) }; xhr.open('PUT', resourceData.uploadUrl); xhr.setRequestHeader('Content-Type', resourceData.contentType); xhr.send({ uri: file }); }) }Y llame a esta función desde su código como:
let isSuccess = await uploadImage({ contentType: "image/jpeg", uploadUrl: "http://my.super.web.amazon.service..." }, "file:///path-to-file-in-filesystem.jpeg")Fuente: https://github.com/react-native-community/react-native-image-picker/issues/61#issuecomment-297865475
No necesita usar react-native-fs o esa biblioteca de búfer. En su lugar, simplemente lea el archivo usando https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsArrayBuffer y pase el resultado al parámetro del cuerpo de recuperación. readAsBinaryString y readAsDataUrl me dieron resultados extraños.
Nota: no tuve que agregar "; charset=utf-8" a mi encabezado de tipo de contenido.
Ejemplo:
const fileReader = new FileReader(); fileReader.addEventListener('load', (event: any) => { const buffer = event.target.result; return fetch(link.url, { method: 'PUT', body: buffer, }) .then((response) => { if (!response.ok) { throw new Error( `${response.status}: ${response.statusText}` ); } return response; }) .then(resolve, reject); }); fileReader.addEventListener('error', reject); fileReader.addEventListener('abort', reject); fileReader.readAsArrayBuffer(file);