1

Note: working great with image

Below is the code to select image/video

await launchImageLibrary(options, response => {
    if (response.didCancel) {
    } else if (response.error) {
    } else if (response.customButton) {
    } else {
      let url = await UploadResource(response.assets[0]);
    }
    this.clickUpload = false;
  });

And this is my uploadResourse file

import { s3bucket } from '../aws/configration';
import * as env from '../config/environment';
import fs from 'react-native-fs'; 
import * as mime from 'react-native-mime-types'; 
import { decode } from './Base64ToArrayBuffer';

export async function UploadResource(file){
//   if (isLoading) return;
  return new Promise(async (resolve, reject) => {
    console.log(file);
    let contentType = mime.lookup(file.uri);
    if(contentType===false)
    contentType='video/mp4' 
    const base64 = await fs.readFile(file.uri, 'base64');
    const fileName = file.fileName || String(Date.now())+String(Date.now());
    const contentDeposition = 'inline;filename="' + fileName + '"';
    const arrayBuffer = decode(base64);  // it is return me an empty array
    const params = { 
      Bucket: env.Bucket,
      Key: fileName,
      Body: arrayBuffer, 
      ContentDisposition: contentDeposition,
      ContentType: contentType,
    };
      s3bucket.upload(params, (err, data) => {
          if (err) {
              console.log(err);
              reject(err);
          } 
          else { 
              resolve(data.Location);
          } 
      });
  })
};

Below is code for decode

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

const lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
for (let i = 0; i < chars.length; i++) {
    lookup[chars.charCodeAt(i)] = i;
}
export const decode = (base64) => {
    let bufferLength = base64.length * 0.75,
        len = base64.length,
        i,
        p = 0,
        encoded1,
        encoded2,
        encoded3,
        encoded4;

    if (base64[base64.length - 1] === '=') {
        bufferLength--;
        if (base64[base64.length - 2] === '=') {
            bufferLength--;
        }
    }

    const arraybuffer = new ArrayBuffer(bufferLength),
        bytes = new Uint8Array(arraybuffer);

    for (i = 0; i < len; i += 4) {
        encoded1 = lookup[base64.charCodeAt(i)];
        encoded2 = lookup[base64.charCodeAt(i + 1)];
        encoded3 = lookup[base64.charCodeAt(i + 2)];
        encoded4 = lookup[base64.charCodeAt(i + 3)];

        bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
        bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
        bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
    }

    return arraybuffer;
};

the issue which can be is my imagelibrary returning me video path instead of uri of cache.

It is also mentioned here in docs https://github.com/react-native-image-picker/react-native-image-picker#asset-object

The file uri in app specific cache storage. Except when picking video from Android gallery where you will get read only content uri, to get file uri in this case copy the file to app specific storage using any react-native library.

What should I do in my current code to solve it.

Gourav Goel
  • 63
  • 1
  • 7

1 Answers1

0

URI Path returned by react-native-image-picker is a reference to the video not actually video raw data.

A common solution is to fetch video data as BLOB and then let AWS encode it to the target video format (MP4, MKV, AVI,...).


 const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.onload = function () {
      resolve(xhr.response);
    };

    xhr.ontimeout = function (e) {
      // XMLHttpRequest timed out. Do something here.
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", file.uri, true);
    xhr.timeout = 1000 * 60;
    xhr.send(null);
  });

// Upload BLOB raw data with AWS-SDK 

Fiston Emmanuel
  • 4,242
  • 1
  • 8
  • 14