There is such a problem. To transfer files in an Android application, we use a Socket, we encrypt and transfer to the server, there the data is decrypted and transmitted by the usual POST method, but when some data is transferred, the file is not loaded, but returns 500 The error stream terminated unexpectedly. One xlsx file is transferred. but the other is gone. We also saw that if the file is still uploaded to the server and we download it, the file is broken and at the end a piece of header Content-Disposition: form-data; name = "publicAccess" false.
ANDROID CODE
#Override
public void run() {
try {
byte[] request = new byte[4096];
byte[] reply = new byte[8192];
final InputStream inFromClient = sClient.getInputStream();
final OutputStream outToClient = sClient.getOutputStream();
SSLSocket remoteSocket = tlsConnectionService.createSSLSocket(remoteHost, remotePort);
final InputStream inFromServer = remoteSocket.getInputStream();
final OutputStream outToServer = remoteSocket.getOutputStream();
// a new thread for uploading to the server
new Thread() {
public void run() {
int bytes_read;
try {
while ((bytes_read = inFromClient.read(request)) != -1 ) {
String newReq = new String(request);
if (newReq != null) {
outToServer.write(newReq.replace(LOCAL_SOCKET_URL, remoteHost).getBytes(), 0, bytes_read);
outToServer.flush();
}
}
} catch (IOException e) {
if (!(e instanceof SocketException)) {
Log.e(M.CPP, e.toString());
}
}
}
}.start();
// current thread manages streams from server to client (DOWNLOAD)
int bytes_read;
try {
while ((bytes_read = inFromServer.read(reply)) != -1 ) {
outToClient.write(reply, 0, bytes_read);
outToClient.flush();
}
} catch (IOException e) {
Log.e(M.CPP, e.toString());
} finally {
try {
remoteSocket.close();
} catch (IOException e) {
Log.e(M.CPP, e.toString());
}
}
sClient.close();
} catch (IOException e) {
Log.e(M.CPP, e.toString());
}
}
Server CODE
#PostMapping(
value = {"/file", "/file/" },
consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public ResponseEntity<FileEntryDto> upload(
#PathVariable("source") String source,
#AuthenticationPrincipal JwtUserDetails currentUser,
#Validated FileUploadRequest request
) {
return ResponseEntity.ok(
converters.fileToDto(
fileOperationService.upload(Source.fromName(source), request, currentUser.getUserId()))
);
}
The request that we see when inspecting app
request
Related
I've implemented a REST webservice for uploading a file to my server:
#Path("/upload")
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_XML)
public javax.ws.rs.core.Response uploadNewAdvJson(#FormDataParam("file") InputStream is) {
boolean res = true;
OutputStream out = null;
try {
File directory = new File("myFolder");
if (!directory.exists()) {
directory.mkdirs();
}
out = new FileOutputStream(new File("myFolder" + File.separator + "myFile.png"));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = is.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
res = false;
if (out != null) {
try {
out.close();
out.flush();
} catch (IOException e1) {
// do nothing
}
}
}
return new Response();
}
(where Response is my JAXB response Object).
I'm testing this service with this client:
public class Test {
public static void main(String[] args) {
final Client client = ClientBuilder.newBuilder().register(MultiPartFeature.class).build();
final FileDataBodyPart filePart = new FileDataBodyPart("file", new File("pathToImage/imgToUpload.png");
FormDataMultiPart formDataMultiPart = new FormDataMultiPart();
final FormDataMultiPart multipart = (FormDataMultiPart) formDataMultiPart.field("foo", "bar").bodyPart(filePart);
final WebTarget target = client.target("http://localhost:8080/myServer/rest/uploadNewAdv");
final Response response = target.request().post(Entity.entity(multipart, multipart.getMediaType()));
try {
formDataMultiPart.close();
multipart.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
But it doesn't work as i expect. In fact, a myFile.png is created and saved, but has different size than imageToUpload.png and i can't open it as an image (looks like a corrupted file).
What's wrong?
I have tried everything to get this to work. Basically I have an Android App which receives data from a Python based Server on a local network connection. I can receive Data no problem. However when I attempt to send data back the App crashes and the Python server receives blank data. I have tried several different approaches but non have worked. Here is the Python method I have written to receive the message:
def checkReply(self):
reply = "no reply yet"
self.conn.settimeout(1)
try:
test = self.conn.recv(1024)
except:
self.conn.timeout;
print("I failed to hear this") #Debug to help see if I have heard an incomming message
try:
data = test.decode()
reply = data
except:
print("I failed to decode this") #Debug to help see if I could not decode an incomming message
print(reply)
self.conn.settimeout(0)
My client on my Android application looks like this:
public class Client extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "No data has been sent yet";
TextView textResponse;
Socket socket = null;
Client(String addr, int port, TextView textResponse) {
dstAddress = addr;
dstPort = port;
this.textResponse = textResponse;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(
1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
/*
* notice: inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
response = byteArrayOutputStream.toString("Ascii");
}
byteArrayOutputStream.flush();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
protected String getSite(){
return response;
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void returnMsg(){
try (DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream())) {
byte[] buf = "hello".getBytes("UTF-8");
outToClient.writeBytes("Test");
outToClient.flush();
} catch (IOException e) {}
}
}
I am having to test on a physical device so I have no log to trace the error message. Any help would be greatly appreciated. Thanks
I managed to solve the issue. I needed to flush the buffer before trying to send any data back via the socket
when I download the file it always throw this Exception:
org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 210846; received: 0
my code:
String fileid=attachment.getBoxfileid();
String sha1=attachment.getSha1();
String filename=attachment.getFilename();
final String clientid=ToolsUtils.getBOXcomConfig().get(ToolsUtils.CLIENTID);
final String clientsecret=ToolsUtils.getBOXcomConfig().get(ToolsUtils.CLIENTSECRET);
BoxOAuthToken authToken=this.boxuploadService.getTokenByClientId(clientid);
BoxClient boxClient=new BoxClient(clientid,clientsecret,null,null,new BoxConfigBuilder().build());
boxClient.authenticate(authToken);
boxClient.addOAuthRefreshListener(new OAuthRefreshListener() {
#Override
public void onRefresh(IAuthData authData) {
boxuploadService.updateBoxAccessToken(clientid,authData.getAccessToken(),authData.getRefreshToken());
}
});
BoxDefaultRequestObject obj = new BoxDefaultRequestObject();
obj.getRequestExtras().setIfMatch(sha1);
DownloadFileRequest downloadFileRequest=new DownloadFileRequest(new BoxConfigBuilder().build(), new BoxJSONParser(new BoxResourceHub()), fileid, obj);
out = response.getOutputStream();
InputStream inputStream=boxClient.getFilesManager().downloadFile(fileid, obj);
byte[] buffer = new byte[1024];
response.setContentType("application/octet-stream" );
response.setHeader( "Content-Disposition", "attachment; filename=\"" + filename + "\"" );
while((readCount = inputStream.read(buffer)) > 0) {
out.write(buffer, 0, readCount);
}
out.flush();
It looks like the reading part went wrong, did you catch any exception when calling downloadFile(fildId, requestObject) ?
my code looks like below :
try {
BoxDefaultRequestObject requestObject = new BoxDefaultRequestObject();
inputStream = boxClient.getFilesManager().downloadFile(fileId,
requestObject);
} catch (BoxRestException e) {
e.printStackTrace();
} catch (BoxServerException e) {
e.printStackTrace();
} catch (AuthFatalFailureException e) {
e.printStackTrace();
}
you can check whether the InputStream object is correctly generated by this way.
I was making a Java application that relies on setting http.proxyPort and http.proxyHost. There are two processes: One is the regular program, the other is the proxy. I have a simple socket listener running on http.proxyPort (which I control). It's as simple as
while (true) {
try {
Socket connection = server.accept();
Handler handler = new Handler(connection);
handler.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
So whenever "process 1" makes an http request - like
URL yahoo = new URL("http://www.google.ca/");
URLConnection yc = yahoo.openConnection();
System.out.println(yc.getClass().getName());
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
It goes through the proxy. Now what if the client is using an HTTPS protocol? Like instead use https://google.ca? There's a property https.proxyPort and https.proxyHost, but I've literally been trying for months (on and off, it's not too important) without luck. I've read a bunch of threads (I will list some at the end so you know I have done something).
My closest attempt so far:
Server
try {
System.setProperty("javax.net.ssl.keyStore", "test.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "2520xe");
SSLServerSocketFactory sslserversocketfactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslserversocket =
(SSLServerSocket) sslserversocketfactory.createServerSocket(9999);
System.out.println("Ready");
SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();
InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
OutputStream toClient = sslsocket.getOutputStream();
toClient.write(("HTTP/1.0 200 Connection established\n" +
"Content-Length: " + "Shut down!".getBytes().length
+ "\r\n").getBytes("utf-8"));
toClient.write("Shut down!".getBytes("utf-8"));
toClient.close();
} catch (Exception exception) {
exception.printStackTrace();
}
Client
try {
System.setProperty("https.proxyHost", "127.0.0.1");
System.setProperty("https.proxyPort", "9999");
URL yahoo = new URL("https://www.google.ca/");
URLConnection yc = yahoo.openConnection();
System.out.println(yc.getClass().getName());
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
And I get this error javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? I googled it but came up with some mail stuff instead.
Basically, I need to create a java proxy server, that's set to the client by the https.proxyPort and https.proxyHost flags, and can send data back to the client app, which may not be modified in any way (it's just using URL connection = new URL("https://..."))
A few of the sites I tried...
creating a Java Proxy Server that accepts HTTPS
http://stilius.net/java/java_ssl.php
There was something else about getting Java to accept all certificates, but I can't find any of the links. I have the code, but I encountered more errors than the thing I'm doing right now, but I can include it if it helps (I didn't initially because this is already a long question)
As auntyellow commented: you don't need to do any SSL-fiddling yourself. Basically https-proxying is about forwarding binary data between two parties.
To cite draft-luotonen-web-proxy-tunneling-01.txt:
CLIENT -> SERVER SERVER -> CLIENT
-------------------------------------- -----------------------------------
CONNECT home.netscape.com:443 HTTP/1.0
User-agent: Mozilla/4.0
<<< empty line >>>
HTTP/1.0 200 Connection established
Proxy-agent: Netscape-Proxy/1.1
<<< empty line >>>
<<< data tunneling to both directions begins >>>
So basically you need to ensure you trust your client enough to connect from your proxies firewall-position to the given host and port. Because of this common practice is to limit allowed port to 443, reject connection to localhost and from "untrusted" parties.
This is a "simple" server which is usable as https.proxy in Java if you are not jet convinced:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created for http://stackoverflow.com/q/16351413/1266906.
*/
public class Server extends Thread {
public static void main(String[] args) {
(new Server()).run();
}
public Server() {
super("Server Thread");
}
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(9999)) {
Socket socket;
try {
while ((socket = serverSocket.accept()) != null) {
(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
return;
}
}
public static class Handler extends Thread {
public static final Pattern CONNECT_PATTERN = Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])",
Pattern.CASE_INSENSITIVE);
private final Socket clientSocket;
private boolean previousWasR = false;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
String request = readLine(clientSocket);
System.out.println(request);
Matcher matcher = CONNECT_PATTERN.matcher(request);
if (matcher.matches()) {
String header;
do {
header = readLine(clientSocket);
} while (!"".equals(header));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(clientSocket.getOutputStream(),
"ISO-8859-1");
final Socket forwardSocket;
try {
forwardSocket = new Socket(matcher.group(1), Integer.parseInt(matcher.group(2)));
System.out.println(forwardSocket);
} catch (IOException | NumberFormatException e) {
e.printStackTrace(); // TODO: implement catch
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 502 Bad Gateway\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
return;
}
try {
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 200 Connection established\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
Thread remoteToClient = new Thread() {
#Override
public void run() {
forwardData(forwardSocket, clientSocket);
}
};
remoteToClient.start();
try {
if (previousWasR) {
int read = clientSocket.getInputStream().read();
if (read != -1) {
if (read != '\n') {
forwardSocket.getOutputStream().write(read);
}
forwardData(clientSocket, forwardSocket);
} else {
if (!forwardSocket.isOutputShutdown()) {
forwardSocket.shutdownOutput();
}
if (!clientSocket.isInputShutdown()) {
clientSocket.shutdownInput();
}
}
} else {
forwardData(clientSocket, forwardSocket);
}
} finally {
try {
remoteToClient.join();
} catch (InterruptedException e) {
e.printStackTrace(); // TODO: implement catch
}
}
} finally {
forwardSocket.close();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
}
private static void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[4096];
int read;
do {
read = inputStream.read(buffer);
if (read > 0) {
outputStream.write(buffer, 0, read);
if (inputStream.available() < 1) {
outputStream.flush();
}
}
} while (read >= 0);
} finally {
if (!outputSocket.isOutputShutdown()) {
outputSocket.shutdownOutput();
}
}
} finally {
if (!inputSocket.isInputShutdown()) {
inputSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
private String readLine(Socket socket) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int next;
readerLoop:
while ((next = socket.getInputStream().read()) != -1) {
if (previousWasR && next == '\n') {
previousWasR = false;
continue;
}
previousWasR = false;
switch (next) {
case '\r':
previousWasR = true;
break readerLoop;
case '\n':
break readerLoop;
default:
byteArrayOutputStream.write(next);
break;
}
}
return byteArrayOutputStream.toString("ISO-8859-1");
}
}
}
Default java SE7 implementation of URLConnection for HTTPS protocol uses parameters
https.proxyHost and https.proxyPort
Add to Tomcat:
-Dhttps.proxyHost="192.168.121.31" -Dhttps.proxyPort="3128"
Im unable to do HTTP POST using J2ME below is the code that im using which is throwing an exception when I try and write to the OutputStrem.
In the code Below SYSO prints "here5". Please need some guidance. Basically I've put the http connection part in a separate threads run method, to keep it aloof from the UI thread.
public void run(){
HttpConnection http = null;
OutputStream out = null;
String msg = "lat=10&long=20&mac=923873";
try{
String url = "http://xxxx.php";
byte[] data = null;
InputStream istrm = null;
http = (HttpConnection)Connector.open(url);
}
catch(Exception e)
{
System.out.println("here1");
}
try
{
http.setRequestMethod(HttpConnection.POST);
}
catch(Exception e)
{
System.out.println("here2");
}
try{
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
http.setRequestProperty("User-Agent", "HttpMidlet/0.2");
http.setRequestProperty("Custom-Property", "MyCustomProperty/1.0; AnotherProperty/debug_0.1");
http.setRequestProperty("Content-Length", ""+msg.getBytes().length);
}
catch(Exception e)
{
System.out.println("here3");
}
try{
out = http.openOutputStream();
}
catch(Exception e)
{
System.out.println("here4");
}
try{
out.write(msg.getBytes());
out.flush();
}
catch(Exception e)
{
System.out.println("here5");
}
}
/**
* Send the data to the URL of Server Site using the POST connection.
*
* #return the response of server.
* #throws Exception
*/
public byte[] send() throws Exception {
HttpConnection hc = null;
InputStream is = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] res = null;
try {
hc = (HttpConnection) Connector.open(url);
hc.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + getBoundaryString());
hc.setRequestMethod(HttpConnection.POST);
OutputStream dout = hc.openOutputStream();
dout.write(postBytes);
if (dout!=null) {
dout.close();
dout = null;
}
int ch;
is = hc.openInputStream();
while ((ch = is.read()) != -1) {
bos.write(ch);
}
res = bos.toByteArray();
} catch (Exception e) {
// if an error occurred connecting to the server.
throw new Exception(e.getMessage());
} finally {
try {
if (bos != null)
bos.close();
if (is != null)
is.close();
if (hc != null)
hc.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
return res;
}
According to this Nokia Sample you do not need to call setRequestProperty methods. Another interesting point is the usage of Connector.open(urlstring, Connector.READ_WRITE).
I resolved this by re-installing the emulator.