Angular weird behaviour when downloading from a stream - java

I have a rest controller in my Java backend to download files as a streams: end points return a StreamingResponseBody stream, when I try to download a file with curl it works fine:
curl -H "Authorization: Bearer <MyToken>" http://localhost:9001/rest/api/download --output test.zip
But not with angular, I'm using HttpModule get method:
this.http.get(url, headers).subscribe ...
However I can see that the file is being downloaded in the network panel of chrome developper tools, but I have no idea where the file is being saved, as if it was streamed instead of downloaded:
Can any body explain this behaviour, and how to download the stream intead of broadcasting it.

Maybe you can try something like...
this.http.get(`your_url`, { headers: headers, responseType: 'blob', observe: 'response'})
.map( res => (
{
content: res.body,
fileName: res.headers.get('content-filename')
}
));
hope this helps!

Related

Post call for file upload not working as expected using java

Post call for file upload not working as expected using java.I need to upload a file using rest call..The file format is correct and its working perfectly in postman and ui side also but in java its giving "Incorrect file format" as the file is not getting uploaded it seems. Am i missing any header or anything.
File file = new File("/Users/surya/Downloads/2021-06-16.xlsx");
Response response = RestAssured
.given()
.multiPart("file", file, "multipart/form-data")
.post("http://myuploadsite.com/upload/feedfile");
System.out.println(response.asString());
My postman curl request
curl --location --request POST 'http://myuploadsite.com/upload/feedfile' \
--header 'Content-Type: multipart/form-data; boundary=jena' \
--header 'Host;' \
--form 'file=#"/Users/surya/Downloads/2021-06-16.xlsx"'
Method you're using is:
RequestSpecification multiPart(String controlName, File file, String mimeType);
You need to define mimeType for file you're uploading, in this case is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet or application/vnd.ms-excel. I'm not quite sure which one.
or just leave blank to use overload method:
RequestSpecification multiPart(String controlName, File file);
Code would be:
File file = new File("/Users/surya/Downloads/2021-06-16.xlsx");
Response response = RestAssured
.given()
.multiPart("file", file, "application/vnd.ms-excel")
.post("http://myuploadsite.com/upload/feedfile");
System.out.println(response.asString());
Content-Type: multipart/form-data will be automatically defined by Rest-Assured when you use multipart
https://github.com/rest-assured/rest-assured/wiki/Usage#multi-part-form-data

Send binary data from nodejs (request) to java (ZipInputStream)

For some reason zip files produced on nodeJS gets rejected on a Java server where you can only use "binary" data upload.
If I post the file with Postman using binary it works fine, but when sending through nodeJS (request/request-promise/http ...etc) it does not work.
It gives:
java.util.zip.ZipException: only DEFLATED entries can have EXT descriptor
at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:310)
at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122)
at com.ws...
The files are valid (it accepts via postman!)
Spent nearly two days on this issue. Read through tons on stack overflow post (most of them did not have proper answer in this specific topic) and googled around, but all the efforts in vain.
I kept experimenting and the only solution which seemed to work just fine is using child process and curl...
In case someone else falls into this really annoying problem:
var exec = require('child_process').exec;
var args = "-X POST \
https://mywebsite.com/zip-upload \
-H 'Authorization: Bearer gFChWxzeCIZVLM2q...WlvDB6zq2uOHfUcdX' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/zip' \
--data-binary #./data.zip";
exec('curl ' + args, function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
In my opinion, child_process is the last choice. If you have tried request or request-promise and failed, how about trying htp:
const htp = require('htp');
htp.post(
"https://mywebsite.com/zip-upload",
{ "Authorization" : "earer gFChWxzeCIZVLM2q...WlvDB6zq2uOHfUcdX"
, "Cache-Control" : "no-cache"
, "Content-Type" : "application/zip"
},
fs.createReadStream("./data.zip")
)
.then(function(response) { /* ... */ })
.catch(function(error) { /* ... */ })
;
I was facing similar problem. In my case, I was using custom value for Content-Type (e.g. - "application/abc+json") to upload a zip file via POST request in fetch(). It was working in Postman, but not in nodejs server.
I was able to get it working by adding Content-Length as header before making request via fetch().
Request headers I used - Content-Type, Content-Length, Authorization, and bunch of other API specific headers.
Hopefully this helps anyone facing issue.

Convert Python request with image to cURL

I found this example of a API request. Unfortunately I didn't find any other example how to upload an image to the API.
As I'm not familiar with Python I'm trying to understand how to do the same in a cURL command.
import requests
auth_headers = {
'app_id': 'your_app_id',
'app_key': 'your_app_key'
}
url = 'https://XXXXXXX'
files = {
'source': open('media/test.jpg')
}
data = {
'timeout': 60
}
response = requests.post(url, files=files, data=data, headers=auth_headers)
I tried to convert it by trying out a cURL to python converter, but I don't know how to build it with the files.
In the end I want to do the request in JAVA, but I think if I would know the request in cURL I can figure it out.
Hope anyone can help me with that.
This will do it:
#!/bin/bash
args=(
-H 'app_id: your_app_id'
-H 'app_key: your_app_key'
-F 'source=#/path/to/file'
-F 'timeout=60'
'http://httpbin.org/post'
)
curl "${args[#]}"
or, as a one-liner:
curl -H 'app_id: your_app_id' -H 'app_key: your_app_key' -F 'source=#/path/to/file' -F 'timeout=60' 'http://httpbin.org/post'
Use -H to specify header fields (repeat for every field) and -F to specify form fields - either as key=value pairs, or filename=#path pairs. When -F is used, POST method is the default, and Content-Type is multipart/form-data (but that too can be overridden).

Cannot call Bitcoin RPC from Jersey HttpClient

im using dropwizard. From a resource i try to use bitcoin rpc via Jersey HttpClient.
using curl works like a charm:
$ curl --user user:password -X POST -d '{"jsonrpc": "1.0", "id":"curltest", "method": "getinfo", "params":
[] }' -H 'content-type: text/plain;' http://domain.name:18332/
But somehow using Jersey HTTP client from a resource doesnt work:
//init in run methode
final Client client = new JerseyClientBuilder(e).using(c.getJerseyClientConfiguration()).build(getName());
HTTPBasicAuthFilter httpBasicAuth = new HTTPBasicAuthFilter("user", "password");
client.addFilter(httpBasicAuth);
//From the resource
WebResource webRes = client.resource("http://domain.name:18332/");
webRes.header("content-type", "text/plain");
RPC_REQUEST rpc = new RPC_REQUEST("1.0", "curltest", "getinfo", new ArrayList<String>());
String response = webRes.post(String.class, JSONParserHelper.parseJSONToString(rpc));
JSONParserHelper.parseJSONToString(rpc) returns following string:
{"jsonrpc":"1.0","id":"curltest","method":"getinfo","params":[]}
Following error is caused in row "webRes.post":
! com.sun.jersey.api.client.UniformInterfaceException: Client response status: 500
EDIT: Using a wrong pw causes a 401. I guess the connection should be correct and the issue is somewhere else.
EDIT: Used -d instead of --data-binary
EDIT: As soon as Im home Ill dump the whole request from jersey http client.
Thank you
Bitcoin RPC does not support chunked encoding requests.
Since there was a bug in dropbox jersey libs till 0.8 you cannot disable it.
Since 0.8 you can disable it in the configuration file.
I had to migrate from 0.7 to 0.8 and add this in my configuration file.
httpClient:
...
chunkedEncodingEnabled: false
By the way a good migration overview: https://groups.google.com/forum/#!topic/dropwizard-dev/VInOW_ebiAc

What content-type does dropbox (file put) api uses? and How to mimic it?

I was reading the files_put documentation for the Dropbox API.
The URL Path they use is: https://api-content.dropbox.com/1/files_put/<root>/<path>?param=val and request body holds the file:
required The file contents to be uploaded. Since the entire PUT body
will be treated as the file, any parameters must be passed as part of
the request URL. The request URL should be signed just as you would
sign any other OAuth request URL.
Questions
I am curious to know what is the content-type of this type of request? (file in request body and parameters in url string)
How can this API functionality be mimics? specifically in a grails controller. Something like this.
How would this type of request be tested in cURL Update : I found out how to test this with curl here.
For the controller I envisioned something like this
def save () {
withFormt {
html {actForHTML}
<something> {actForREST}
}
}
def actForREST () {
//how can I get access to the file? I guess url parameters can be accessed by `params`
}
REST console does not have the ability to send binary data in request body. Unfortunately, I cannot access curl right now. But I have few inputs for you, and I am also going to try the same in my personal machine.
How to use curl for file upload? (#source - cURL docs)
4.3 File Upload POST
Back in late 1995 they defined an additional way to post data over HTTP. It
is documented in the RFC 1867, why this method sometimes is referred to as
RFC1867-posting.
This method is mainly designed to better support file uploads. A form that
allows a user to upload a file could be written like this in HTML:
<form method="POST" enctype='multipart/form-data' action="upload.cgi">
<input type=file name=upload>
<input type=submit name=press value="OK">
</form>
This clearly shows that the Content-Type about to be sent is
multipart/form-data.
To post to a form like this with curl, you enter a command line like:
curl --form upload=#localfilename --form press=OK [URL]
W3C Specification
Have a look at the W3C Spec here and the RFC1867 for multipat/form-data
Grails Controller to handle request
Your app should be able to handle the multipart/form-data(no MIME type addition should be required, I think). Your action in the controller should look like below:-
For example:
def uploadFileAndGetParams(){
def inputStream = request.getInputStream()
byte[] buf = new byte[request.getHeaders().CONTENT_LENGTH] //Assuming
//Read the input stream
for (int chunk = inputStream.read(buf); chunk != -1; chunk = is.read(buf)){
//Write it any output stream
//Can refer the content-type of the file (following W3C spec)
//and create an Output stream accordingly
}
//Get the params as well
//params.foo //params.bar
}
It may not be full proof but it should be less complicated than what I thought it would be. I am going to try the same today. Useful post to look at.

Categories

Resources