I faced with next issue: some of Dialogflow V2 HTTP API requests response with incomplete body. No regularity found, it can happen during random requests with different intent & session info.
Example:
POST https://dialogflow.googleapis.com/v2/projects/{project-name}/agent/sessions/{session-uuid}:detectIntent
> Content-Type: application/json
> Authorization: Bearer {token}
REQUEST BODY:
{
"queryInput": {
"audioConfig": {
"audioEncoding": "AUDIO_ENCODING_OGG_OPUS",
"sampleRateHertz": 48000,
"languageCode": "en-US",
"model": "command_and_search"
}
},
"inputAudio": "{base64-encoded-file}"
}
RESPONSE:
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=UTF-8
RESPONSE BODY:
{
"queryResult": {
"languageCode": "en-US"
}
}
... and that's all. API returns body with languageCode field only in queryResult. All are missing except this one.
Issue happen only during requests with audio, all works fine for text input.
Any help/tips how to avoid this issue? I would be grateful for any help.
I have checked out the documentation [1] and it seems to me you are using a sampling interval different than the sampling interval of the default format.
Particularly, as you can see "Opus encoded audio frames in Ogg container (OggOpus). sampleRateHertz must be 16000."
Meanwhile you specified "sampleRateHertz": 48000.
This may be the reason of your unexpected results. If the sampling rate are different, then you may have a wrong identification of the signal. I would suggest you to resample the audio in input to 16000 Hz or to change the encoding format, and perhaps opting for FLAC (Free Lossless Audio Codec) because is the recommended encoding because it is lossless (therefore recognition is not compromised)
[1] https://cloud.google.com/dialogflow/docs/reference/rest/v2beta1/QueryInput#audioencoding
I am trying to mock the request to upload a zip file through 'POST' method using Wiremock. But I could not find the required property for that. Following is my mocked request which needs to be sent.
How can I save this file to the _file directory through POST request?
"request":
{
"url": "/order/uploadFile",
"method": "POST",
"headers": {
"token": {
"equalTo": "0000000"
},
"Content-Type":{
"equalTo": "multipart/form-data"
}
},
"bodyPatterns": [{
"equalToJson": "{\"sampleFile\":\"Sample_file.zip\"}"}]
} ....```
Here is the postman request. [![request-postman][1]][1]
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/CQaSj.png
In short: you can't save anything to the __files directory using the out-of-the-box standalone WireMock from withing a mapping rule. This functionality requires a custom extension that needs to do the saving for you.
That said, it is possible, according to this Stack Overflow answer to store a file in __files using a PUT on /__admin/files/[your desired filename]. This will then create a new file under the __files. It appears to be undocumented and as such may not feature in future versions. Sub-folders seem to go unsupported when I tried it.
I simply took an example from Postman API Documentation for Create Collection and removed the extra request outside the folder.
My intention is to create just a folder with 1 request in it.
Here is the request:
{
"collection":{
"variables":[
],
"info":{
"name":"Sample Collection",
"description":"This is just a sample collection.",
"schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
},
"item":[
{
"name":"This is a folder",
"description":"",
"item":[
{
"name":"Sample POST Request",
"request":{
"url":"echo.getpostman.com/post",
"method":"POST",
"header":[
{
"key":"Content-Type",
"value":"application/json",
"description":""
}
],
"body":{
"mode":"raw",
"raw": "{
\"data\": \"123\"
}"
},
"description":"This is a sample POST Request"
},
"response":[
]
}
]
}
]
}
}
But for this, I am getting "Bad Request" error, what exactly is wrong with my request?
EDIT - Here's what it looks like in Postman
To me, it looks like you’re trying to send the whole collection json file back to that route.
The JSON in the request body on the image is what you would import into Postman to get the Sample Collection folder. This contains a request called Sample POST Request
Copy the request body JSON and save it as a .json file - Then import this using the Import feature in the top left on the application.
This will then create the folder for you in the application with the sample POST request.
If you send it to the echo URL, you will receive a response telling you that the URL has now changed to https://postman-echo.com/post - Add this new URL into the address bar and hit Send.
I am calling a web service from Classic ASP/VBScript. The call expects 3 parameters, 1 which is form data and 2 which are optional file data. Currently not sending the file data.
The form data is multiple fields, wrapped up in json.
So I'm setting the content-type on the ServerXMLHTTP object to be multipart/form-data, and I'm creating the json segment as such and sending it as the data
Content-Type: application/json; charset=utf-8
{
"Token": "...",
"FirstName": "First Name",
I keep getting Request must be Content-type: multipart/form-data.
I've tried adding a boundary and same thing.
I know I can do this in C# using MultipartFormDataContent, but it has to be Classic unfortunately.
What's the correct way to send? Thanks!
I have a REST web service that currently exposes this URL:
http://server/data/media
where users can POST the following JSON:
{
"Name": "Test",
"Latitude": 12.59817,
"Longitude": 52.12873
}
in order to create a new Media metadata.
Now I need the ability to upload a file at the same time as the media metadata. What's the best way of going about this? I could introduce a new property called file and base64 encode the file, but I was wondering if there was a better way.
There's also using multipart/form-data like what a HTML form would send over, but I'm using a REST web service and I want to stick to using JSON if at all possible.
I agree with Greg that a two phase approach is a reasonable solution, however I would do it the other way around. I would do:
POST http://server/data/media
body:
{
"Name": "Test",
"Latitude": 12.59817,
"Longitude": 52.12873
}
To create the metadata entry and return a response like:
201 Created
Location: http://server/data/media/21323
{
"Name": "Test",
"Latitude": 12.59817,
"Longitude": 52.12873,
"ContentUrl": "http://server/data/media/21323/content"
}
The client can then use this ContentUrl and do a PUT with the file data.
The nice thing about this approach is when your server starts get weighed down with immense volumes of data, the url that you return can just point to some other server with more space/capacity. Or you could implement some kind of round robin approach if bandwidth is an issue.
Just because you're not wrapping the entire request body in JSON, doesn't meant it's not RESTful to use multipart/form-data to post both the JSON and the file(s) in a single request:
curl -F "metadata=<metadata.json" -F "file=#my-file.tar.gz" http://example.com/add-file
on the server side:
class AddFileResource(Resource):
def render_POST(self, request):
metadata = json.loads(request.args['metadata'][0])
file_body = request.args['file'][0]
...
to upload multiple files, it's possible to either use separate "form fields" for each:
curl -F "metadata=<metadata.json" -F "file1=#some-file.tar.gz" -F "file2=#some-other-file.tar.gz" http://example.com/add-file
...in which case the server code will have request.args['file1'][0] and request.args['file2'][0]
or reuse the same one for many:
curl -F "metadata=<metadata.json" -F "files=#some-file.tar.gz" -F "files=#some-other-file.tar.gz" http://example.com/add-file
...in which case request.args['files'] will simply be a list of length 2.
or pass multiple files through a single field:
curl -F "metadata=<metadata.json" -F "files=#some-file.tar.gz,some-other-file.tar.gz" http://example.com/add-file
...in which case request.args['files'] will be a string containing all the files, which you'll have to parse yourself — not sure how to do it, but I'm sure it's not difficult, or better just use the previous approaches.
The difference between # and < is that # causes the file to get attached as a file upload, whereas < attaches the contents of the file as a text field.
P.S. Just because I'm using curl as a way to generate the POST requests doesn't mean the exact same HTTP requests couldn't be sent from a programming language such as Python or using any sufficiently capable tool.
One way to approach the problem is to make the upload a two phase process. First, you would upload the file itself using a POST, where the server returns some identifier back to the client (an identifier might be the SHA1 of the file contents). Then, a second request associates the metadata with the file data:
{
"Name": "Test",
"Latitude": 12.59817,
"Longitude": 52.12873,
"ContentID": "7a788f56fa49ae0ba5ebde780efe4d6a89b5db47"
}
Including the file data base64 encoded into the JSON request itself will increase the size of the data transferred by 33%. This may or may not be important depending on the overall size of the file.
Another approach might be to use a POST of the raw file data, but include any metadata in the HTTP request header. However, this falls a bit outside basic REST operations and may be more awkward for some HTTP client libraries.
I don't understand why, over the course of eight years, no one has posted the easy answer. Rather than encode the file as base64, encode the json as a string. Then just decode the json on the server side.
In Javascript:
let formData = new FormData();
formData.append("file", myfile);
formData.append("myjson", JSON.stringify(myJsonObject));
POST it using Content-Type: multipart/form-data
On the server side, retrieve the file normally, and retrieve the json as a string. Convert the string to an object, which is usually one line of code no matter what programming language you use.
(Yes, it works great. Doing it in one of my apps.)
I realize this is a very old question, but hopefully this will help someone else out as I came upon this post looking for the same thing. I had a similar issue, just that my metadata was a Guid and int. The solution is the same though. You can just make the needed metadata part of the URL.
POST accepting method in your "Controller" class:
public Task<HttpResponseMessage> PostFile(string name, float latitude, float longitude)
{
//See http://stackoverflow.com/a/10327789/431906 for how to accept a file
return null;
}
Then in whatever you're registering routes, WebApiConfig.Register(HttpConfiguration config) for me in this case.
config.Routes.MapHttpRoute(
name: "FooController",
routeTemplate: "api/{controller}/{name}/{latitude}/{longitude}",
defaults: new { }
);
If your file and its metadata creating one resource, its perfectly fine to upload them both in one request. Sample request would be :
POST https://target.com/myresources/resourcename HTTP/1.1
Accept: application/json
Content-Type: multipart/form-data;
boundary=-----------------------------28947758029299
Host: target.com
-------------------------------28947758029299
Content-Disposition: form-data; name="application/json"
{"markers": [
{
"point":new GLatLng(40.266044,-74.718479),
"homeTeam":"Lawrence Library",
"awayTeam":"LUGip",
"markerImage":"images/red.png",
"information": "Linux users group meets second Wednesday of each month.",
"fixture":"Wednesday 7pm",
"capacity":"",
"previousScore":""
},
{
"point":new GLatLng(40.211600,-74.695702),
"homeTeam":"Hamilton Library",
"awayTeam":"LUGip HW SIG",
"markerImage":"images/white.png",
"information": "Linux users can meet the first Tuesday of the month to work out harward and configuration issues.",
"fixture":"Tuesday 7pm",
"capacity":"",
"tv":""
},
{
"point":new GLatLng(40.294535,-74.682012),
"homeTeam":"Applebees",
"awayTeam":"After LUPip Mtg Spot",
"markerImage":"images/newcastle.png",
"information": "Some of us go there after the main LUGip meeting, drink brews, and talk.",
"fixture":"Wednesday whenever",
"capacity":"2 to 4 pints",
"tv":""
},
] }
-------------------------------28947758029299
Content-Disposition: form-data; name="name"; filename="myfilename.pdf"
Content-Type: application/octet-stream
%PDF-1.4
%
2 0 obj
<</Length 57/Filter/FlateDecode>>stream
x+r
26S00SI2P0Qn
F
!i\
)%!Y0i#.k
[
endstream
endobj
4 0 obj
<</Type/Page/MediaBox[0 0 595 842]/Resources<</Font<</F1 1 0 R>>>>/Contents 2 0 R/Parent 3 0 R>>
endobj
1 0 obj
<</Type/Font/Subtype/Type1/BaseFont/Helvetica/Encoding/WinAnsiEncoding>>
endobj
3 0 obj
<</Type/Pages/Count 1/Kids[4 0 R]>>
endobj
5 0 obj
<</Type/Catalog/Pages 3 0 R>>
endobj
6 0 obj
<</Producer(iTextSharp 5.5.11 2000-2017 iText Group NV \(AGPL-version\))/CreationDate(D:20170630120636+02'00')/ModDate(D:20170630120636+02'00')>>
endobj
xref
0 7
0000000000 65535 f
0000000250 00000 n
0000000015 00000 n
0000000338 00000 n
0000000138 00000 n
0000000389 00000 n
0000000434 00000 n
trailer
<</Size 7/Root 5 0 R/Info 6 0 R/ID [<c7c34272c2e618698de73f4e1a65a1b5><c7c34272c2e618698de73f4e1a65a1b5>]>>
%iText-5.5.11
startxref
597
%%EOF
-------------------------------28947758029299--
To build on ccleve's answer, if you are using superagent / express / multer, on the front end side build your multipart request doing something like this:
superagent
.post(url)
.accept('application/json')
.field('myVeryRelevantJsonData', JSON.stringify({ peep: 'Peep Peep!!!' }))
.attach('myFile', file);
cf https://visionmedia.github.io/superagent/#multipart-requests.
On the express side, whatever was passed as field will end up in req.body after doing:
app.use(express.json({ limit: '3MB' }));
Your route would include something like this:
const multerMemStorage = multer.memoryStorage();
const multerUploadToMem = multer({
storage: multerMemStorage,
// Also specify fileFilter, limits...
});
router.post('/myUploads',
multerUploadToMem.single('myFile'),
async (req, res, next) => {
// Find back myVeryRelevantJsonData :
logger.verbose(`Uploaded req.body=${JSON.stringify(req.body)}`);
// If your file is text:
const newFileText = req.file.buffer.toString();
logger.verbose(`Uploaded text=${newFileText}`);
return next();
},
...
One thing to keep in mind though is this note from the multer doc, concerning disk storage:
Note that req.body might not have been fully populated yet. It depends on the order that the client transmits fields and files to the server.
I guess this means it would be unreliable to, say, compute the target dir/filename based on json metadata passed along the file