JAVA HttpsConnection POST send image and text - java

I am trying to send a text and a image via HTTP POST and I always get a 400 error. I would like to use it to send a image via Telegram bot and I am using the code provided in this answer with a text and bite parameters https://stackoverflow.com/a/2793153/1970613 with small modifications.
What could be the error ?
String param = "chat_id=mi_id&photo=";
String charset = "UTF-8";
String request = "https://api.telegram.org/bot-botCOde/sendPhoto";
URL url = new URL( request );
File binaryFile = new File("/home/joseantonio/imagen.jpg");
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
String boundary = Long.toHexString(System.currentTimeMillis());
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setDoOutput( true );
conn.setInstanceFollowRedirects( false );
conn.setRequestMethod( "POST" );
conn.setRequestProperty( "charset", "utf-8");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
conn.setUseCaches( false );
try {
OutputStream output = conn.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF).append(param).append(CRLF).flush();
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: image/jpg").append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(binaryFile.toPath(), output);
output.flush(); // Important before continuing with writer!
writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF).flush();
int responseCode2 = conn.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + request);
System.out.println("Response Code : " + responseCode2);```

I believe the fact that you are using https url is the cause of the error you are getting. You need to handle things a little different when you are submitting to an https url. See an example here

Related

android multipart/form-data POST get 400 error

I should send text/image files to one website using POST method.
But, I couldn't get 200 code after my MainActivity.
my code block
String crlf = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
System.out.println("[Request] routine is started.");
URL url = new URL(_url);
urlConn = (HttpURLConnection) url.openConnection();
// [2-1]. urlConn setting
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
urlConn.setUseCaches(false);
urlConn.setRequestMethod("POST"); // URL method : POST.
urlConn.setRequestProperty("Connection", "keep-alive");
urlConn.setRequestProperty("Cache-Control", "no-cache");
urlConn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
// [2-2]. parameter send and read data
OutputStream os = urlConn.getOutputStream();
DataOutputStream request = new DataOutputStream(os);
// Write key and values
// 1. Access Key
request.writeBytes(twoHyphens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data; name=\"accessKey\"" + crlf);
request.writeBytes("Content-Type: application/json" + crlf);
request.writeBytes(crlf);
request.writeBytes(accessKey + crlf);
// 2. Image data
request.writeBytes(twoHyphens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data; name=\"files\"" + crlf);
request.writeBytes("Content-Type: image/jpeg" + crlf);
request.writeBytes(crlf);
request.write(imageBytes);
request.writeBytes(crlf);
request.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
request.flush();
request.close();
int response_code = urlConn.getResponseCode();
System.out.println("Connection response code : [" + response_code + "]");
I think my DataOutputStream code is not bad, but I get 400 error:
I/System.out: [Request] routine is started.
D/EGL_emulation: app_time_stats: avg=45.59ms min=8.56ms max=670.08ms count=23
I/System.out: Connection response code : [400]
I/System.out: [doInBackground] output : Response Code : 400
I/System.out: [onPostExecute] routine is started.
I/System.out: [onPostExecute] output : Response Code : 400
What's wrong?

Sending Image files and Text from android app java HttpURLConnection multipart form-data

Hi I am trying to upload a file and a text, using multipart form-data HttpURLConnection java, sample of code below:
String boundary = UUID.randomUUID().toString();
final String LINE_FEED = "\r\n";
OutputStream outputStream;
PrintWriter writer;
URL url_upload = new URL(url_api );
HttpURLConnection conn = (HttpURLConnection) url_upload.openConnection();
conn.setUseCaches(false);
conn.setDoOutput(true); // indicates POST method
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty( "Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0");
conn.setRequestProperty("Connection", "Keep-Alive");
outputStream = conn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"), true);
//DataOutputStream request = new DataOutputStream(conn.getOutputStream());
//Username
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + "Username" + "\"")
.append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=").append("UTF-8").append(
LINE_FEED);
writer.append(LINE_FEED);
writer.append(Username).append(LINE_FEED);
writer.flush();
//Password
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + "Password" + "\"")
.append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=").append("UTF-8").append(
LINE_FEED);
writer.append(LINE_FEED);
writer.append(Password);
writer.flush();
writer.append(LINE_FEED);
if(Food_image_file_name != null)
{
Log.i("File:", String.valueOf(file1));
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + "file1" + "\"; filename=\"").append(file1.getName()).append("\"")
.append(LINE_FEED);
writer.append("Content-Type: ").append(URLConnection.guessContentTypeFromName(file1.getName()))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary");
writer.append(LINE_FEED);
writer.flush();
writer.append(LINE_FEED);
FileInputStream inputStream = new FileInputStream(String.valueOf(file1.toPath()));
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
writer.append(LINE_FEED).flush();
writer.append("--").append(boundary).append("--").append(LINE_FEED);
writer.close();
additional details:
I/File:: /storage/emulated/0/DCIM/100ANDRO/DSC_0117.JPG
I/Api response: 400, Bad Request
Note:
I tested server from postman, and it working with no issues with Postman, the files where uploaded successful to the server from postman.
This link is another post of a sample of a web api i am using to read the request: link_here
Update:
I had to modify my web api a bit as i wasn't using properly, the code works fine now
I/File:: /storage/emulated/0/Pictures/Viber/IMG-8bf36fec3b3c01df23c7faf763e2eac7-V.jpg
I/Boundary: ****
I/Image Content type: image/jpeg
and in Blob images Azure, i see that the image it is not visible, it is corrupted.
so my last issue was in write of the image, correct code below, works like a charm now ;):
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + "file1" + "\"; filename=\"").append(file1.getName()).append("\"")
.append(LINE_FEED);
writer.append("Content-Type: ").append(mimeType)
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
so my last issue was in write of the image, correct code below, works like a charm now ;):
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + "file1" + "\"; filename=\"").append(file1.getName()).append("\"")
.append(LINE_FEED);
writer.append("Content-Type: ").append(mimeType)
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush()

[HttpURLConnection]How to send a post request with form-data

I am faced with a problem regarding to the HttpURLConnection. I want to send a POST request with 2 keys in the body (form-data).
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
// add header
con.setRequestProperty("Content-Type", "multipart/form-data");
con.setRequestProperty("cookie", cookies);
con.setDoInput(true);
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
How do I add the body (form-data)?
For example, I would to add 2 keys, name: "abc" and password: "abc": Form-Data Image
Use Content-Disposition: form-data; followed by form-data parameters.
String name = "abc";
String password = "abc";
String crlf = "\r\n";
wr.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"; password=\"" + password + "\""+ crlf);

Error code:500 received in HttpsURLConnection

I am sending a HttpsURLConnection request to a server which requires a basic auth with it. I have provided the authorization value and verified it as well. But I'm getting a Http status 500: Internal Server error. Here is my code:
public String httptest(String url, File f, String username, String password) throws Exception {
// Task attachments endpoint
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
// Set basic auth header
String apiKey = username + ":" + password;
String basicAuth = "Basic " + new String(new Base64().encode(apiKey.getBytes()));
connection.setRequestProperty("Authorization", basicAuth);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
logger.info("basicAuth: " + basicAuth);
// Indicate a POST request
connection.setDoOutput(true);
// A unique boundary to use for the multipart/form-data
String boundary = Long.toHexString(System.currentTimeMillis());
String fboundary = "----WebKitFormBoundary" + boundary + "u0gW";
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + fboundary);
// Construct the body of the request
logger.info("boundary: " + fboundary);
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
String fileName = f.getName();
String ffname = fileName.substring(fileName.lastIndexOf("\\")+1);
writer.append("--" + fboundary).append(LINE_FEED);
writer.append("Content-Disposition: multipart/form-data; name=\"file\"; filename=\"" + ffname + "\"").append(LINE_FEED);
writer.append("Content-Type: application/x-zip-compressed").append(LINE_FEED);
writer.append(LINE_FEED);
logger.info("fileName: " + fileName);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
for (String line; (line = reader.readLine()) != null; ) {
writer.append(line).append(LINE_FEED);
}
} finally {
if (reader != null) try {
reader.close();
} catch (IOException logOrIgnore) {
}
}
writer.append(LINE_FEED);
writer.append("----" + fboundary).append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
writer.close();
} catch (Exception e) {
System.out.append("Exception writing file" + e);
} finally {
if (writer != null) writer.close();
}
logger.info("ResponseCode: " + connection.getResponseCode());
//System.out.println(connection.getResponseCode()); // Should be 200
return connection.getResponseMessage();
}
When I send the same request through postman client, It works fine. Here are the headers from the postman request:
Authorization: Basic c2dveWFsQHF1YXJrLmNvbTpRdWFyazEyMw==
Cache-Control: no-cache Postman-Token:
d6fac5f0-e844-9bac-2bce-51580fdd5557 Content-Type:
multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="file"; filename="Tiger522.zip" Content-Type:
application/x-zip-compressed
----WebKitFormBoundary7MA4YWxkTrZu0gW
Please tell me what to do?
I can see two possible errors:
As StephaneM pointed out: The content-disposition of the file upload must be "form-data", not "multipart/form-data":
writer.append("Content-Disposition: form-data; name=\"file\";
filename=\"" + ffname + "\"").append(LINE_FEED);
You specify "Content-Type: application/x-zip-compressed" for the file upload. This means zip format. You are however just writing a file in there, using InputStreamReader. This does not seem to be a zip format that you are writing.

GAE sending post request with multipart/form-data, file from blobstore with SSL

I want to upload a file from the blobstore to a service called Wisita.
Here is the documentation for the upload API :
http://wistia.com/doc/upload-api
Here is my code so far (I think i might missing the ssl option)
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile binaryFile = fileService.getBlobFile(new BlobKey("my blob key"));
String param = "api_password=" + URLEncoder.encode("my wisita key", "UTF-8") +
"&project_id=" + URLEncoder.encode("folder_id", "UTF-8");
String charset = "UTF-8";
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
URLConnection connection = new URL("https://upload.wistia.com/").openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
OutputStream output = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!
// Send normal param.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(param).append(CRLF).flush();
// Send binary file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getNamePart() + "\"").append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getNamePart())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
InputStream input = null;
try {
FileReadChannel ch = fileService.openReadChannel(binaryFile, true);
input = Channels.newInputStream(ch);
byte[] buffer = new byte[1024];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
output.flush(); // Important! Output cannot be closed. Close of writer will close output as well.
} finally {
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
writer.append(CRLF).flush(); // CRLF is important! It indicates end of binary boundary.
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF);
//resp part
InputStream responseStream = new BufferedInputStream(connection.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null)
{
stringBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = stringBuilder.toString();
resp.getWriter().write(response);
} finally {
if (writer != null) writer.close();
}
I got a 500 error with this code
Thank you for your question. As a reference it solved the issue I was having doing a similar task.
The first change I made to my code was to set both the doOutput and the doInput to true (not just the doOutput). I'm not sure if that makes a difference, since I believe true is the default.
con.setDoOutput(true);
con.setDoInput(true);
Are you sure your content is being encoded correctly? I used the same setup and configuration you have, but instead of using a PrintWriter, I just called write and passed it the bytes from my String and bytes from my File contents:
connection.getOutputStream().write("Content-Disposition blah...".getBytes());
connection.getOutputStream().write(fileContentsByteArray);
connection.flush();
I then just read the data I needed back from my web service by reading from the connection's input stream like this:
FileOutputStream out = new FileOutputStream("received.bin");
InputStream in = connection.getInputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
How about change passing normal parameters?
Before:
param=..api_password...project_id...;
// Send normal param.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(param).append(CRLF).flush();
After:
// Send normal param.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"api_password\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(api_password).append(CRLF).flush();
// Send normal param.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"project_id\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(project_id).append(CRLF).flush();

Categories