Upload a file but set Content-Type

眉间皱痕 提交于 2019-12-11 10:39:11

问题


I got Watson Speech-to-Text working on the web. I am now trying to do it on react native but am getting errors on the file upload part.

I am using the HTTPS Watson API. I need to set the Content-Type otherwise Watson returns a error response. However in react-native, for the file upload to work, we seem to need to set 'Content-Type' to 'multipart/form-data'. Is there anyway to upload a file in react-native while setting Content-Type to 'audio/aac'?

The error Watson API gives me if I set 'Content-Type': 'multipart/form-data' is:

{
    type: "default",
    status: 400,
    ok: false,
    statusText: undefined,
    headers: Object,
    url: "https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?continuous=true",
    _bodyInit: Blob,
    _bodyBlob: Blob
}

The response body is:

{
   "code_description": "Bad Request", 
   "code": 400, 
   "error": "No JSON object could be decoded"
}

Here is my code (full code is here - gist.github.com ):

    const ext = 'aac';
    const file_path = '/storage/emulated/0/Music/enter-the-book.aac';
    data.append('file', {
        uri: `file://${file_path}`,
        name: `recording.${ext}`,
        type: `audio/${ext}`
    }, `recording.${ext}`);

    const response = await fetch('https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?continuous=true', {
        method: 'POST',
        headers: {
            // 'Content-Type': `audio/${ext}`,
            'Content-Type': 'multipart/form-data',
            'X-Watson-Authorization-Token': token
        },
        body: data
    });

    console.log('watson-stt::getResults - response:', response);

    if (response.status !== 200) {
        const error = await response.text();
        throw new Error(`Got bad response "status" (${response.status}) from Watson Speach to Text server, error: "${error}"`);
}

Here is a screenshot of the error I get when I set 'Content-Type': 'audio/aac':


回答1:


According to the documentation for multipart requests the request should be:

curl -X POST -u "{username}":"{password}"
--header "Transfer-Encoding: chunked"
--form metadata="{
  \"part_content_type\":\"audio/flac\",
  \"timestamps\":true,
  \"continuous\":true}"
--form upload="@audio-file1.flac"
"https://stream.watsonplatform.net/speech-to-text/api/v1/recognize"

So the content-type should be multipart/form-data, you can specify aac as "part_content_type": "audio/aac".

The big problem you have is that audio/aac is not in supported formats. You might probably need another codec.




回答2:


Thanks so much to DanielBolanos and NikolayShmyrev this is the solution I used:

This code is for iOS so I recorded the audio as blah.ulaw BUT the part_content_type is aduio/mulaw;rate=22050 this is very important to use mulaw even though file ext is ulaw. An interesting note: I couldn't play the blah.ulaw file on my macOS desktop.

Also note that you MUST NOT set Content-Type to multipart/form-data this will destroy the boundary.

Also Bluemix requires rate in the part_content_type for mulaw

const body = new FormData();
let metadata = {
    part_content_type: 'audio/mulaw;rate=22050'  // and notice "mulaw" here, "ulaw" DOES NOT work here
};
body.append('metadata', JSON.stringify(metadata));
body.append('upload', {
    uri: `file://${file_path}`,
    name: `recording.ulaw`, // notice the use of "ulaw" here
    type: `audio/ulaw` // and here it is also "ulaw"
});

const response = await fetch('https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?continuous=true', {
    method: 'POST',
    headers: {
        // 'Content-Type': 'multipart/form-data' // DO NOT SET THIS!! It destroys the boundary and messes up the request
        'Authorization': `Basic ${btoa(`${USERNAME}:${PASSWORD}`)}`
    },
    body
});


来源:https://stackoverflow.com/questions/44106529/upload-a-file-but-set-content-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!