1

When I try to upload Image from React Native + Expo app to Azure Blob Storage via Azure Functions (Node.js), image(jpeg) can be saved into the storage but that image cannot be opened correctly.

Evidence

== ASK ==

・How can I upload image? (Current behavior explained in below troubleshooting steps is unexpected? if so, how can I prevent it and upload image precisely..?)

== Assumption ==

・React Native 0.63.2

・Expo 42.0.4

・Expo-Image-Picker 10.2.3

・Request Route :

React Native + Expo App -> API (Azure Functions (Node.js)) -> Azure Blob Storage

== My Code ==

= React Native + Expo (Client Side)

*I implemented based on below discussion: How can I upload a photo with Expo?

*params : returned value from expo-image-picker after image select

const formData = new FormData();
const imageUri = params.uri;
const dataType = mime.getType(imageUri);
const fileName = imageUri.split("/").pop();

formData.append('image',{
    uri: imageUri,
    name: "a.jpg", 
    type: dataType
} as any);

const url = 'xxxxx';
await fetch (url, {
    method: 'POST',
    headers:{
    },
    body:formData
})

expo-image-picker side code (pass the value of "result" to the above code.)

const pickImage = async () =>{
    console.log("PICKIMAGE CALLED.");

    // Access Permission Check
    let permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
    if (permissionResult.granted === false) {
      alert("Permission to access camera roll is required!");
      return;
    }

    // Image Pickup
    try{
    let result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.All,
        allowsEditing: false,
        aspect: [4,3],
        quality:  0.5,
        base64: true,
    });
    if (!result.cancelled) {
        setImageData(result);
    }
    } catch(E){
    console.log(E);
    }
};

= Azure Function (Server Side)

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const replace = require('buffer-replace');

// Upload Image 
try{
    // Parse Blob Data
    var multipart = require("parse-multipart");
    var bodyBuffer = Buffer.from(req.body);
    var boundary = multipart.getBoundary(req.headers['content-type']);
    var parts = multipart.Parse(bodyBuffer, boundary);

    // Upload Blob to Azure Storage
    const {BlobServiceClient} = require("@azure/storage-blob");
    const containerName = "ContainerName";
    const blobName = parts[0].filename;

    const blobServiceClient = BlobServiceClient.fromConnectionString("connection string of storage");
    const containerClient = blobServiceClient.getContainerClient(containerName);
    const blockBlobClient = containerClient.getBlockBlobClient(blobName);
    const uploadBlobResponse = await blockBlobClient.upload(parts[0].data, parts[0].data.length);
    context.log("Blob was uploaded successfully. requestId: ", uploadBlobResponse.requestId);

    context.done();

== Troubleshootings ==

1, When I checked Azure Function side log, "parts" seems have incorrect binary(hex) data. I mean, before "ff d8" (indicator of jpeg format), unexpected line break "0d 0a" seems added. I doubt this is the reason file cannot be opened precisely.

var parts = multipart.Parse(bodyBuffer, boundary);

Result of context.log(parts)

2, Based on the result of 1, I also checked same thing from client side (React Native + Expo) with below code, and found unexpected line break "0d 0a" is not there. So wondering why unexpected line break is added while processing at server side.

  function base64ToHex(str) {
       const raw = atob(str);
       let result = '';
       for (let i = 0; i < raw.length; i++) {
          const hex = raw.charCodeAt(i).toString(16);
          result += (hex.length === 2 ? hex : '0' + hex);
       }
       return result.toUpperCase();
  }
  
  console.log(base64ToHex(params.base64));

Result of Client Side

3: Try Image Upload from Postman.

Request Route : Postman -> API (Azure Functions) -> Azure Blob Storage.

The way to send image is little different from that of React Native + Expo app (Postman: seems add image file (blob?) directly into the formdata, ReactNative: add blob uri, mime etc into formdata), but It succeeded.

Postman's request configuration

Thank you very much for your help!!

Yutaro
  • 11
  • 2

0 Answers0