Upload audio to server expo react-native

152 views Asked by At

I am recording audio in Expo React Native using expo-av and expo-file-system, saving the recorded file as an MP3, and then uploading it to the server. When I test it using Postman, everything works fine. However, when I try to upload the file in my code, the API returns a (400) Bad Request error. Here is my code:

const [recording, setRecording] = useState(null);
const [voice, setVoice] = useState('uk');
const [isRecording, setIsRecording] = useState(false);

const startRecording = async () => {
    try {
        const { status } = await Audio.requestPermissionsAsync();
        if (status !== 'granted') {
            console.error('Permission to access audio was denied');
            return;
        }

        const recording = new Audio.Recording();
        await recording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
        await recording.startAsync();
        setRecording(recording);
        setIsRecording(true);
    } catch (error) {
        console.error('Error starting recording: ', error);
    }
};

const stopRecording = async () => {
    try {
        await recording.stopAndUnloadAsync();
        setIsRecording(false);
        const fileDirectory = FileSystem.documentDirectory || FileSystem.cacheDirectory;
        const fileName = 'recording.mp3';
        const filePath = `${fileDirectory}${fileName}`;

        await FileSystem.moveAsync({
            from: recording.getURI(),
            to: filePath,
        });

        const formData = new FormData();
        formData.append('file', {
            uri: filePath,
            type: 'audio/mpeg',
            name: 'recording.mp3',
        });
        formData.append('expectedText', 'Hello');
        formData.append('extension', 'mp3');

        const response = await axios.post(
            `http://192.168.10.16/erp-pronounciation/pronunciation/file/uk`,
            formData,
            {
                headers: {
                    'Content-Type': 'multipart/form-data',
                },
            }
        );

        console.log('Upload successful', response.data);
    } catch (error) {
        console.error('Error stopping recording or saving file: ', error);
    }
};

backend code using .Net core:

using System.Diagnostics;
using System.Dynamic;
using System.Net;
using System.Text;
using Navi.SundayQ.Pronunciation.Extensions;
using Navi.SundayQ.Pronunciation.Models.Pronunciation;
using Newtonsoft.Json;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

var configuration = builder.Configuration;
const string outputAudioExt = ".wav";

app.Use(async (context, next) =>
{
    if (context.Request.Method == "OPTIONS")
    {
        context.Response.StatusCode = 200;

        await WriteCorsAsync(context);

        await context.Response.WriteAsync("");
    }
    else
    {
        context.Response.OnStarting(WriteCorsAsync, context);

        await next(context);
    }

    static Task WriteCorsAsync(object state)
    {
        var context = (HttpContext)state;

        context.Response.Headers.Add("Access-Control-Allow-Origin", context.Request.Headers.Origin);
        context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
        context.Response.Headers.Add("Access-Control-Allow-Methods",
            string.Join(", ",
                new[] { context.Request.Method }.Union(
                    context.Request.Headers.AccessControlRequestMethod.Select(v => v))));
        context.Response.Headers.Add("Access-Control-Allow-Headers",
            string.Join(", ",
                context.Request.Headers.Select(p => p.Key)
                    .Union(context.Request.Headers.AccessControlRequestHeaders.Select(v => v))));

        return Task.CompletedTask;
    }
});

app.MapPost("/pronunciation/file/{accent:regex(^u(s|k)$)}",
    (HttpContext context, ILogger<Program> logger, string accent) =>
    {
        string expectedText = context.Request.Form["expectedText"];
        if (string.IsNullOrEmpty(expectedText))
            expectedText = context.Request.Query["expectedText"];

        if (string.IsNullOrEmpty(expectedText))
            return Results.BadRequest();

        var file = context.Request.Form.Files["file"];
        if (file == null)
            return Results.BadRequest();

        var extension = Path.GetExtension(file.FileName)?.ToLower();
        if (!new[] { ".wav", ".mp3", ".ogg" }.Contains(extension))
            return Results.BadRequest();

        string audioBase64 = null;
        try
        {
            if (extension.Equals(outputAudioExt))
            {
                using var ms = new MemoryStream();
                file.CopyTo(ms);
                audioBase64 = Convert.ToBase64String(ms.ToArray());
            }
            else
            {
                var dir = Path.Combine(Directory.GetCurrentDirectory(), "Shared", "Temp");
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);

                var fileInput = Path.Combine(dir, Guid.NewGuid() + extension);
                using var s = File.Create(fileInput);
                file.CopyTo(s);
                s.Close();
                s.Dispose();

                audioBase64 = ConvertAudiAndGetBase64(fileInput);
            }
        }
        catch (Exception e)
        {
            logger.LogError(e, "ERROR");
        }

        if (string.IsNullOrEmpty(audioBase64))
            return Results.Problem();

        try
        {
            var result = GetPronunciationResult(accent, expectedText, audioBase64);
            return Results.Json(result);
        }
        catch (Exception e)
        {
            logger.LogError(e, "ERROR");
        }

        return Results.StatusCode(500);
    });



string ConvertAudiAndGetBase64(string fileInput)
{
    var fileOutput = fileInput + outputAudioExt;
    var cmdFfmpeg = configuration.GetValue<string>("FfmpegCmd");
    var process = new Process
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = cmdFfmpeg,
            Arguments = $"-y -i \"{fileInput}\" \"{fileOutput}\"",
            CreateNoWindow = true,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        }
    };

    process.Start();
    process.WaitForExit();

    string audioBase64 = null;
    if (File.Exists(fileOutput))
    {
        audioBase64 = Convert.ToBase64String(File.ReadAllBytes(fileOutput));
        File.Delete(fileOutput);
    }

    if (File.Exists(fileInput))
        File.Delete(fileInput);

    return audioBase64;
}

ExpandoObject GetPronunciationResult(string accent, string expectedText, string base64)
{
    using var webClient = new WebClient();
    webClient.Encoding = Encoding.UTF8;
    webClient.Headers.Add("x-blobr-key", configuration.GetValue<string>("PronunciationApiKey"));
    webClient.Headers.Add("Content-Type", "application/json");
    var json =
        webClient.UploadString(configuration.GetValue<string>("PronunciationApiUrl").Replace("{accent}", accent),
            JsonConvert.SerializeObject(new
            {
                audio_base64 = base64,
                audio_format = "wav",
                expected_text = expectedText
            }));

    return JsonConvert.DeserializeObject<ExpandoObject>(json);
}

app.Run();

0

There are 0 answers