I'm trying to upload an image to the PushBullet API with retrofit.
After the upload-request I fire the multipart upload.
With retrofit I get this error:
{"error":{"code":"invalid_request","type":"invalid_request","message":"Invalid multipart body.","cat":"o(^・x・^)o"},"error_code":"invalid_request"}
The problem only occurs in my java code and not with the PAW HTTP-Client.
# PAW generated Request
POST /upload-legacy/bcSWXnBjNIwpkej7CxfIHFz0ugXO6yhf HTTP/1.1
Content-Type: multipart/form-data; charset=utf-8; boundary=__X_PAW_BOUNDARY__
Host: upload.pushbullet.com
Connection: close
User-Agent: Paw/3.0.12 (Macintosh; OS X/10.11.6) GCDHTTPRequest
Content-Length: 34508
--__X_PAW_BOUNDARY__
Content-Disposition: form-data; name="file"; filename="cat.jpg"
Content-Type: image/jpeg
...
# Retrofit generated Request
POST https://upload.pushbullet.com/upload-legacy/ZZ4fLcqt2WFQmlbKTDlgcYXtB3KiCs3M http/1.1
Content-Type: multipart/form-data; charset=utf-8
Content-Length: 2012
Content-Disposition: form-data; name="file"; filename="1475501429665_motion_detected.jpg"
Content-Type: image/jpeg; charset=utf-8
Content-Length: 1772
...
The important difference I think is the Content-Length in the Part.
I found this issue, but that would mean the PushBullet API is non-compliant with the HTTP specification?
Any help would be appreciated.
I was experiencing this same issue in Google Apps Script, which is JavaScript based, but I'm hoping my solution could help anyone else experiencing this issue. I used TANAIKE's method of building the multipart request here: https://gist.github.com/tanaikech/d595d30a592979bbf0c692d1193d260c
My successful end result looked like this for successfully uploading a JPEG:
// https://docs.pushbullet.com/v8/#upload-request
// Assuming var picResponseJSON is your JSON results from successful upload-request
var uploadJSON = {
awsaccesskeyid: picResponseJSON.data.awsaccesskeyid,
acl: picResponseJSON.data.acl,
key: picResponseJSON.data.key,
signature: picResponseJSON.data.signature,
policy: picResponseJSON.data.policy,
"content-type": picResponseJSON.data["content-type"],
};
// https://gist.github.com/tanaikech/d595d30a592979bbf0c692d1193d260c
var boundary = "xxxxxxxxxx";
var data = "";
for (var i in uploadJSON) {
data += "--" + boundary + "\r\n";
data +=
'Content-Disposition: form-data; name="' +
i +
'"; \r\n\r\n' +
uploadJSON[i] +
"\r\n";
}
data += "--" + boundary + "\r\n";
data +=
'Content-Disposition: form-data; name="file"; filename="' +
fileTitle +
'"\r\n';
data += "Content-Type:" + mimeType + "\r\n\r\n";
var payload = Utilities.newBlob(data)
.getBytes()
.concat(DriveApp.getFileById(fileID).getBlob().getBytes())
.concat(Utilities.newBlob("\r\n--" + boundary + "--").getBytes());
var options3 = {
method: "post",
contentType: "multipart/form-data; boundary=" + boundary,
payload: payload,
muteHttpExceptions: true,
};
// Send request
var uploadResponse = UrlFetchApp.fetch(picResponseJSON.upload_url, options3);
// Confirm it's successful
if (uploadResponse.getResponseCode() == 204) {
console.log("Success! File: " + picResponseJSON.file_url);
}
Please note the Blob functions in the payload are part of Google Apps Script so modify accordingly for your language.
Related
I need consume a service, the file is a excel.
But when I execute the consume the response is this "returned a response status of 400 Bad Request"
String authString = name + ":" + password;
Client restClient = Client.create();
String authStringEnc = Base64.getEncoder().encodeToString(authString.getBytes());
// the file to upload, represented as FileDataBodyPart
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file", new File(file),
MediaType.APPLICATION_OCTET_STREAM_TYPE);
// fileDataBodyPart.setContentDisposition(FormDataContentDisposition.name("file").fileName(file).build());
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.field("spId", idServicio, MediaType.MULTIPART_FORM_DATA_TYPE).bodyPart(fileDataBodyPart);
multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
WebResource webResource = restClient.resource(url);
ClientResponse resp = webResource.header("Authorization", "Basic " + authStringEnc)
.header("Content-Type", "multipart/form-data").post(ClientResponse.class, multiPart);
String output = resp.getEntity(String.class);
System.out.print(output);
return resp;
I put a proxy and I use the Rest client "insomnia" and it works for me by insomnia.
This is the request that sent it:
INSOMNIA
POST /conf/configuration/distribution-files/service HTTP/1.1
Authorization: Basic aW1wbGluZWE6SU1QTElORUE=
User-Agent: insomnia/7.0.6
Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
Accept: */*
Content-Length: 5872
Connection: close
--X-INSOMNIA-BOUNDARY
Content-Disposition: form-data; name="file"; filename="myspprueba.xls"
Content-Type: application/vnd.ms-excel
--X-INSOMNIA-BOUNDARY
Content-Disposition: form-data; name="spId"
5823
This is the request that at the moment i am failing
POST /conf/configuration/distribution-files/service HTTP/1.1
Authorization: Basic aW1wbGluZWE6SU1QTElORUE=
Accept: */*
Content-Type: multipart/form-data; boundary=Boundary_1_2104028992_1577117786190
MIME-Version: 1.0
User-Agent: Java/1.8.0_211
Connection: close
Content-Length: 5994
--Boundary_1_2104028992_1577117786190
Content-Type: text/plain
Content-Disposition: form-data; filename="myspprueba.xls"; modification-date="Thu, 19 Dec 2019 15:52:46 GMT"; size=5632; name="file"
I'm trying to configure and send a multipart request like the following one:
------boundary
Content-Disposition: form-data; name="before"; filename="blob"
Content-Type: application/vnd...+json;type=some_type
{some JSON}
------boundary
Content-Disposition: form-data; name="after"; filename="blob"
Content-Type: application/vnd...+json;type=some_type
{another JSON}
------boundary--
So I tried to configure a request, as in the code below
RestAssuredConfig config = RestAssured.config().multiPartConfig(
new MultiPartConfig().defaultCharset(StandardCharsets.UTF_8).
defaultBoundary("--boundary--"));
MultiPartSpecification m1 new MultiPartSpecBuilder(
new ObjectMapper().writeValueAsString(some_JSON_transformed_to_HashMap)).
fileName("blob").controlName("before").
mimeType(ContentType.TEXT.getAcceptHeader()).
header("ContentType", "application/vnd...+json;type=some_type").build();
MultiPartSpecification m2 = new MultiPartSpecBuilder(
new ObjectMapper().writeValueAsString(another_JSON_transformed_to_HashMap)).
fileName("blob").controlName("after").
mimeType(ContentType.TEXT.getAcceptHeader()).
header("ContentType", "application/vnd...+json;type=some_type").build();
RequestSpecification request = RestAssured.given().multiPart(m1).multiPart(m2).
config(config).
.header("Content-Type", "multipart/form-data; boundary=" + config.getMultiPartConfig().defaultBoundary());
request.post("some_url");
But when I try to execute it, server says that resource is invalid, but I believe, that JSONs is correct, so I suppose my multipart configuration is incorrect. How should I configure a request?
You could try something similar to below code .
given().auth().preemptive()
.basic("Jirausername", "Jirapassword")
.header("X-Atlassian-Token", "nocheck")
.multiPart(new File("/home/users/cat.log"))
.when().post("http://localhost:8181/rest/api/2/issue/STS-223/attachments");
I have a java server using sockets. I have an html file which contains a form that can be used to upload a file and send it. How can the server download that file without blocking. The browser never closes the connection and it just hangs in there I have beeping using readLine() from the input stream but it blocks. is there any way around this?
I appreciate any help here.
Thanks
please clarify your requirement, it seems total chaos in your steps.
did your program run as client side or server side?
could you show your code? and show what blocked you?
It is much better if you can draw a working-flow of your program .
Thanks for your supplement, do you want to upload a files through HTTP(writing in socket way). For this requirement, you could check the link link for how HTTP works
[RFC 1867] (https://www.rfc-editor.org/rfc/rfc1867)
Below is the package of how socket way do:
Suppose the server supplies the following HTML:
<FORM ACTION="http://server.dom/cgi/handle"
ENCTYPE="multipart/form-data"
METHOD=POST>
What is your name? <INPUT TYPE=TEXT NAME=submitter>
What files are you sending? <INPUT TYPE=FILE NAME=pics>
</FORM>
and the user types "Joe Blow" in the name field, and selects a text
file "file1.txt" for the answer to 'What files are you sending?'
The client might send back the following data:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
If the user also indicated an image file "file2.gif" for the answer
to 'What files are you sending?', the client might client might send
back the following data:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"
Content-type: multipart/mixed, boundary=BbC04y
--BbC04y
Content-disposition: attachment; filename="file1.txt"
Nebel & Masinter Experimental [Page 9]
RFC 1867 Form-based File Upload in HTML November 1995
Content-Type: text/plain
... contents of file1.txt ...
--BbC04y
Content-disposition: attachment; filename="file2.gif"
Content-type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif...
--BbC04y--
--AaB03x--
I have server running on port. I want it to gather the data sent by a POST request which carries a file (Not just text but png image).
for example here is a server:
public void run() {
try {
InputStream is = insocket.getInputStream();
PrintWriter out = new PrintWriter(insocket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line;
line = in.readLine();
String request_method = line;
System.out.println("HTTP-HEADER: " + line);
line = "";
// looks for post data
int postDataI = -1;
while ((line = in.readLine()) != null && (line.length() != 0)) {
System.out.println("HTTP-HEADER: " + line);
if (line.indexOf("Content-Length:") > -1) {
postDataI = new Integer(
line.substring(
line.indexOf("Content-Length:") + 16,
line.length())).intValue();
}
}
String postData = "";
// read the post data
if (postDataI > 0) {
char[] charArray = new char[postDataI];
in.read(charArray, 0, postDataI);
postData = new String(charArray);
}
out.println("HTTP/1.0 200 OK");
out.println("Content-Type: text/html; charset=utf-8");
out.println("Server: MINISERVER");
// this blank line signals the end of the headers
out.println("");
// Send the HTML page
out.println("<H1>Welcome to the Mini Server</H1>");
out.println("<H2>Request Method->" + request_method + "</H2>");
out.println("<H2>Post->" + postData + "</H2>");
out.println("<form name=\"input\" action=\"form_submited\" method=\"post\">");
out.println("Username: <input type=\"text\" name=\"user\"><input type=\"submit\" value=\"Submit\"></form>");
out.close();
insocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
How can it be changed to safe a file (Uploaded through HTTP/1.1 POST REQUEST) form) to disk using this server.
Thank you for your time
When I click a button on webpage I get following information in developer tools:
Request URL:https://example.com/path/eventAction.do
Request Method:POST
Status Code:200 OK
and Request headers like below:
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Connection:keep-alive
Content-Length:1600
Content-Type:multipart/form-data; boundary=----
WebKitFormBoundaryZ9ymd7fGOwOFpELi
Cookie:JSESSIONID=C1rX...
and Request payload like:
------WebKitFormBoundaryZ9ymd7fGOwOFpELi
Content-Disposition: form-data; name="example1"
FILTER_900000
------WebKitFormBoundaryZ9ymd7fGOwOFpELi
Content-Disposition: form-data; name="example2"
------WebKitFormBoundaryZ9ymd7fGOwOFpELi
Content-Disposition: form-data; name="example3"
08/03/2018
How can I send this http post with Apache HttpClient or is there any other method to imitate button click event with java code..
Payload parameter can be submitted with HttpPost request by preparing a JSON object as string and calling HttpPost's setEntity method.
payload = "{" +"\"fsName\": \"Peel\", " + "\"name\": \"John\", " + "\"path\": \"/" + accountName + "/invoice/" + sdf2.format(todayDate.toDate()) + "\", " + "}";
strEntity = new StringEntity(payload);
HttpPost().setEntity(strPayload).
I try to communicate between javascript and java. My script javascript send a message to java and java send a response.
javascript part:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4)
{
alert(xmlhttp.responseText);
}
}
var s = "LIGNE \n 2 \n il fait beau \nEND\n";
xmlhttp.open("POST","http://localhost:6020",true);
xmlhttp.send(s);
java part:
try {
serverSocket = new ServerSocket(6020);
} catch (IOException e) {
System.err.println("Could not listen on port: 6020.");
System.exit(-1);
}
serverSocket.accept()
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
String ligne = "";
while(!(ligne = plec.readLine()).equals("END")){
System.out.println(ligne);
}
bw.write("Il fait beau\n");
bw.flush();
bw.close();
plec.close();
socket.close();
output java :
POST / HTTP/1.1
Host: localhost:6020
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://localhost:8080/test.html
Content-Length: 30
Content-Type: text/plain; charset=UTF-8
Origin: http://localhost:8080
Pragma: no-cache
Cache-Control: no-cache
LIGNE
2
il fait beau
So, I receive correctly the message send by javascript but the alert his always empty. How to response at this message?
I try a lot of possiblity but they don't work. And I don't want to use the servlet, it's to heavy to do that.
Thanks.
Edit:
I did this :
bw.write("HTTP/1.1 200 OK\r\n"+
"Content-Type: text/html; charset=utf-8\r\n"+
"Content-Length: 13\r\n\r\n" +
"il fait beau\n");
and this:
String data = "il fait beau \n";
StringBuilder builder = new StringBuilder();
builder.append("HTTP/1.1 200 OK\r\n");
builder.append("Content-Type: text/html; charset=utf-8\r\n");
builder.append("Content-Length:" + data.length() + "\r\n\r\n");
builder.append(data);
bw.write(builder.toString());
But the alert remain empty. Maybe it's a problem in the javascript.
The javascript needs to see a full HTTP response. Merely sending back characters to it, makes it discard the reply as it is an invalid HTTP response.
In your java code, send back something like this
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: <length of data>
---data here---
Reference
Something like:
StringBuilder builder = new StringBuilder();
builder.append("HTTP/1.1 200 OK\r\n");
builder.append("Content-Type: text/plain; charset=utf-8\r\n");
builder.append("Content-Length:" + data.length() + "\r\n\r\n);
builder.append(data);
bw.write(builder.toString());
Try:
bw.write("HTTP/1.1 200 OK\r\n"+
"Content-Type: text/html; charset=utf-8\r\n"+
"Content-Length: 13\r\n\r\n" +
"il fait beau\n");
HTTP-Headers are separated by \r\n (CRLF). Headers and body is spearated by \r\n\r\n.
Note that you set the length to 13 because you also have to count the \n at the end of your string.
EDIT: It does not work because of the cross-domain-policy. http://localhost:6020 is not the same port as the website which executes your JavaScript and so the xmlhttprequest might not be delivered.