android client parse multipart form data to non ascii - android

can you explain why android client parse multiparform data to non ascii chat. while file upload working good using postman
here is my app.js code
var multipart = require('connect-multiparty');
var apiRoutes = require('./routes/apiRoutes');
app.set('views', path.join(__dirname, 'views'));
app.use(logger('dev'));
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded([{extended: false},{ uploadDir:path.join(__dirname, 'uploads') }, {parameterLimit:100000}, {limit: '50mb'}]));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'uploads')));
app.use(multipart());
app.use(apiRoutes);
and apiRoutes point my upload function contain simple print req param.using postman it working good
console.log("mediaChat called", req.body, req.files);
response
mediaChat called { apiKey: '123' } { media:
{ fieldName: 'media',
originalFilename: 'default.png',
path: '/tmp/KFnwsKGp-f4woTaBH6aPR-qa.png',
headers:
{ 'content-disposition': 'form-data; name="media"; filename="default.png"',
'content-type': 'image/png' },
size: 716,
name: 'default.png',
type: 'image/png' } }
here is my android client code (Note this code working file with php $_FILE but not working with express)
com.info.acruss.wave;
import android.os.AsyncTask;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by Naitik on 9/20/2016.
*/
public class UploadImage extends AsyncTask<Void, Void, String> {
String CallingURL;
URL url;
OnTaskCompleted myListener;
private static final String TAG = "UploadImage";
int timeoutMilli = 60000;
String sourceFileUri;
String ApiKey,Type;
public UploadImage(String sourceFileUri, String URL,String apiKey, String type,
OnTaskCompleted listener) {
Log.e("Uploading", "API:" + URL);
this.sourceFileUri = sourceFileUri;
this.CallingURL = URL;
this.myListener = listener;
this.ApiKey=apiKey;
this.Type=type;
try {
url = new URL(CallingURL);
Log.e(TAG, "Url : " + CallingURL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
#Override
protected String doInBackground(Void... params) {
String fileName = sourceFileUri;
HttpURLConnection conn = null;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 10 * 1024 * 1024;
File sourceFile = new File(sourceFileUri);
if (!sourceFile.isFile()) {
Log.e("UploadImage", "Source File Does not exist";
return null;
}
String serverResponseMessage = "";
try {
// open a URL connection to the Servlet
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(CallingURL);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST";
conn.setReadTimeout(timeoutMilli);
conn.setConnectTimeout(timeoutMilli);
conn.setRequestProperty("Connection", "Keep-Alive";
conn.setRequestProperty("ENCTYPE", "multipart/form-data";
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("media", fileName);
conn.setRequestProperty("apiKey",ApiKey);
conn.setRequestProperty("media_type",Type);
conn.setRequestProperty("media", fileName);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name='media';filename='" + fileName + "'" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
int serverResponseCode = conn.getResponseCode();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
StringBuilder responseOutput = new StringBuilder();
while ((line = br.readLine()) != null) {
responseOutput.append(line);
}
br.close();
serverResponseMessage = responseOutput.toString();//output.toString();
Log.e("uploadFile", "HTTP Response is : " + serverResponseMessage);
if (serverResponseCode == 200) {
//status code 200
//status ok
}
//close the streams //
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
ex.printStackTrace();
Log.e("Upload file to server", "error: " + ex.getMessage(), ex);
} catch (Exception e) {
Log.e("Upload file to server", "error: " + e.getMessage(), e);
e.printStackTrace();
}
return serverResponseMessage;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.e("Result", "" + result);
if (myListener != null)
if (result != null) {
myListener.onFileUploadComplete(result);
} else {
myListener.onFileUploadComplete("";
}
}
public interface OnTaskCompleted {
void onFileUploadComplete(String result);
}
}
using android this show wired response as below
mediaChat called { null: '����\u0000\u0010JFIF\u0000\u0001\u0001\u0000\u0000\u0001\u0000\u0001\u0000\u0000��\u0000C\u0000\u0010\u000b\f\u000e\f\n\u0010\u000e\r\u000e\u0012\u0011\u0010\u0013\u0018(\u001a\u0018\u0016\u0016\u00181#%\u001d(:3=Mqypdx\\egc��\u0000C\u0001\u0011\u0012\u0012\u0018\u0015\u0018/\u001a\u001a/cB8Bccccccccccc....
�\u001f.[���_�\u0014)M���XIjX��7�`=�/�8`��ïDʚ\u0018�D���#�V#q~m�q10L�' }
i also tried multer and other multipart handler but noting works.
please help me to out from this hell

It seems the server response is encoded as UTF-8. To properly decode and read you could try
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
Specifying the encoding part to the InputStreamReader will decode and read the stream using specified encoding scheme, which in this case is UTF-8. Check the javadocs for details.

You need to allocate buffer again based on the new size of bufferSize, I have revised the code below:
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = null;
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}

Multipart form submission takes away a lot of the ambiguity that percent-encoding had: the server now can explicitly ask for certain encodings, and the client can explicitly tell the server during the form submission what encoding the fields are in.
There are two ways you go with this functionality: leave it unset and have the browser send in the same encoding as the page, or set it to UTF-8 and then do another conversion server-side. Each method has deficiencies, especially the former.
If you tell the browser to send the form in the same encoding as the page, you still have the trouble of what to do with characters that are outside of the character encoding's range. The behavior, once again, varies: Firefox 2.0 converts them to character entity references while Internet Explorer 7.0 mangles them beyond intelligibility. For serious internationalization purposes, this is not an option.
The other possibility is to set Accept-Encoding to UTF-8, which begs the question: Why aren't you using UTF-8 for everything then? This route is more palatable, but there's a notable caveat: your data will come in as UTF-8, so you will have to explicitly convert it into your favored local character encoding.
A Unicode-based encoding such as UTF-8 can support many languages and can accommodate pages and forms in any mixture of those languages. Its use also eliminates the need for server-side logic to individually determine the character encoding for each page served or each incoming form submission. This significantly reduces the complexity of dealing with a multilingual site or application.
A Unicode encoding also allows many more languages to be mixed on a single page than any other choice of encoding.
have look on Why UTF-X

Related

Trouble on receiving image at an GCP App Engine service running a Flask service

I'm developing an app by enables the user to take a photo and send it to a Keras model for prediction. This model is already deployed in a Google App Engine Service with a Python script that uses Flask for receiving via POST request the image and calling the model to make the prediction. Here's the Python code:
import numpy as np
import flask
import io
import logging
import tensorflow as tf
from keras.preprocessing.image import img_to_array
from keras.applications import imagenet_utils
from keras.models import load_model
from PIL import Image
# initialize our Flask application and the Keras model
app = flask.Flask(__name__)
app.config['PROPAGATE_EXCEPTIONS'] = True
model = None
def recortar(image):
# Function that centers and crop image. Please, asume that it works properly. Return is a numpy array.
return image
#app.route("/predict", methods=["POST"])
def predict():
model = load_model('modelo_1.h5')
graph = tf.get_default_graph()
data = {"success": False}
if flask.request.method == "POST":
if flask.request.files.get("image"):
# read the image in PIL format
image = flask.request.files["image"].read()
image = Image.open(io.BytesIO(image))
image = recortar(image)
app.logger.info('Tamaño: '+str(image.size))
image = img_to_array(image)
image = np.expand_dims(image, axis=0)
with graph.as_default():
preds = model.predict(image)
data['predictions'] = str(np.squeeze(preds).tolist())
data["success"] = True
return flask.jsonify(data)
else:
return "No se ha obtenido la imagen"
else:
return "El HTTP request no era POST"
# if this is the main thread of execution first load the model and
# then start the server
if __name__ == "__main__":
print(("* Loading Keras model and Flask starting server..."
"please wait until server has fully started"))
app.debug = True
app.run()
Sending the image via curl works perfectly: as expected, I obtain a JSON response from the server containing the prediction. Here's the CURL command and the server response:
>> curl -X POST -F image=#nevus.jpg 'https://example.com/predict'
{"predictions":"[0.7404708862304688, 0.25952914357185364]","success":true}
Then I try to repeat the same process, but through an Android app, but I get a 500 error as response. When checking the logs on Stackdriver Error Reporting, I see the following stacktrace:AttributeError:
'NoneType' object has no attribute 'size'
at predict (/home/vmagent/app/main.py:73)
at dispatch_request (/env/lib/python3.6/site-packages/flask/app.py:1799)
at full_dispatch_request (/env/lib/python3.6/site-packages/flask/app.py:1813)
at reraise (/env/lib/python3.6/site-packages/flask/_compat.py:35)
at handle_user_exception (/env/lib/python3.6/site-packages/flask/app.py:1718)
at full_dispatch_request (/env/lib/python3.6/site-packages/flask/app.py:1815)
at wsgi_app (/env/lib/python3.6/site-packages/flask/app.py:2292)
at reraise (/env/lib/python3.6/site-packages/flask/_compat.py:35)
at handle_exception (/env/lib/python3.6/site-packages/flask/app.py:1741)
at wsgi_app (/env/lib/python3.6/site-packages/flask/app.py:2295)
at __call__ (/env/lib/python3.6/site-packages/flask/app.py:2309)
at handle_request (/env/lib/python3.6/site-packages/gunicorn/workers/sync.py:176)
at handle (/env/lib/python3.6/site-packages/gunicorn/workers/sync.py:135)
This error refers to image object, so I assume that, as the code was working properly before, the error must be in the way I send the image through the HTTP request. Recall that the image is taken when a user click a button, because this button sends an intent for taking the photo. When the photo is taken, the user can click a send button, whose code I post bellow. Note that orientedBitmap corresponds to the photo taken in bitmap format.
btn_enviarfoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Botón \"enviar\" pulsado. Codificando imagen.");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
orientedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
orientedBitmap.recycle();
uploadToServer(byteArray);
}
});
uploadToServer just calls the execute methong of AsynchTask class as shown bellow:
private void uploadToServer(byte[] data) {
Bitmap bitmapOrg = BitmapFactory.decodeByteArray(data, 0, data.length);
Log.d(TAG, "Imagen codificada. Enviando al servidor.");
ObtenerPrediccionTask task = new ObtenerPrediccionTask();
task.execute(bitmapOrg);
}
And finally and most important, this is the code for the ObtenerPrediccionTask class:
public class ObtenerPrediccionTask extends AsyncTask<Bitmap, Void, String> {
#Override
protected String doInBackground(Bitmap... imagen) {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
String probabilidad_melanoma = "";
JsonReader jsonReader = null;
try {
for (int i = 0; i < imagen.length; i++) {
Bitmap imagen2 = imagen[i];
imagen2.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte[] ba = bao.toByteArray();
InputStream fileInputStream = new ByteArrayInputStream(ba);
URL url = new URL("https://example.com/predict"); // not the real URL
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "xxxxxxxx";
String str = twoHyphens + boundary + lineEnd;
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"" +
"image" + "\";filename=\"" +
"foto.jpg" + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
int bytesAvailable = fileInputStream.available();
int bufferSize = Math.min(bytesAvailable, 1024);
byte[] buffer = new byte[bufferSize];
// Read file
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, 1024);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
int responseCode = connection.getResponseCode();
connection.getResponseMessage();
fileInputStream.close();
outputStream.flush();
outputStream.close();
if (responseCode == HttpURLConnection.HTTP_OK) {
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();
Log.d(TAG, "Imagen recibida por el servidor y pasada al modelo. Esta es la respuesta: " + response);
jsonReader = new JsonReader(new StringReader(response));
probabilidad_melanoma = readJson(jsonReader);
} else {
Log.d(TAG, Integer.toString(responseCode));
}
}
return probabilidad_melanoma;
} catch (MalformedURLException malformedURLException) {
Log.e(TAG, malformedURLException.toString());
return null;
} catch (IOException io) {
Log.e(TAG, io.toString());
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
protected void onPostExecute(String probabilidad_melanoma) {
if (probabilidad_melanoma != null) {
Log.d(TAG, "Probabilidad melanoma: " + probabilidad_melanoma);
} else {
Log.w(TAG, "La respuesta ha sido nula");
}
}
}
readJson function is also working properly, so don't get bothered by it.
This last chunk of code is the result of an extensive search in SO of a way to properly send an image, but as nothing has worked yet, I've run out of ideas. What's the problem with my code?
The crash traceback indicates that at this line image is None:
app.logger.info('Tamaño: '+str(image.size))
Which means that recortar() returns None, despite your comments:
# Function that centers and crop image. Please, asume that it works properly. Return is a numpy array.
So your the error must be in the way I send the image through the HTTP request assumption might be wrong. Before spending time on that I'd first add checks to ensure that recortar() works properly.

URLConnection always returns 400 : Bad Request when I try to upload a .wav file

I want to implement some code that does exactly what I accomplish when I execute a CURL command in my Mac's terminal, which is to upload a .wav file to a Server.
I already accomplished this for one server before, so my general thinking works (and my code too),
....but now I want to accomplish the same but on a different server.
This time I am having trouble and all I get are "400:Bad Request"
This is he CURL command I want to do on Android, I have added a "-v" so you can see the verbose of my command.
curl -F file=#audio_life.wav 11.2.333.44:14141/transcribe -v
Output log in Terminal:
* Trying 11.2.333.44...
* Connected to 11.2.333.44 (11.2.333.44) port 14141 (#0)
> POST /transcribe HTTP/1.1
> Host: 11.2.333.44:14141
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Length: 304898
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------62142b52672c69e0
>
* Done waiting for 100-continue
< HTTP/1.1 201 Created
< Content-Type: application/json
< Content-Length: 915
This is my code, I always get 400:Bad Request responses, as you can see I have tried to replicate the headers. What am I doing wrong? how can I close in on what the error may be?
String wavpath=Environment.getExternalStorageDirectory().getAbsolutePath()+"/ArtificialSolutions/"+StorageUtils.AUDIO_FILE_NAME+".wav";
File wavfile = new File(wavpath);
FileInputStream fileInputStream = new FileInputStream(wavpath);
connectURL = new URL(ASR_URL_VOCITEC);
String filevalue = StorageUtils.AUDIO_FILE_NAME+".wav";
HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Host","11.2.333.44:14141");
conn.setRequestProperty("User-Agent", "android");
conn.setRequestProperty("Accept","*/*");
conn.setRequestProperty("Transfer-Encoding", "chunked");
conn.setRequestProperty("Expect", "100-continue");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=------------------------f016e997e308ec07");//+boundary);
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"File\""+ lineEnd);
//dos.writeBytes("Content-Disposition: form-data; File=\""+wavpath+"\""+ lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(wavpath);
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[ ] buffer = new byte[bufferSize];
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0){
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
Log.e("joshtag","BytesAvailable: "+bytesAvailable);
bufferSize = Math.min(bytesAvailable,maxBufferSize);
if(bytesAvailable>maxBufferSize){
bytesRead = fileInputStream.read(buffer, 0,bufferSize);
}
else{
bytesRead = fileInputStream.read(buffer, 0,bytesAvailable);
dos.write(buffer, 0, bytesAvailable);
break;
}
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
fileInputStream.close();//63532 , 64556
dos.flush();
Log.e(Tag,"File Sent, Response: "+String.valueOf(conn.getResponseCode()));
Log.e(Tag,"File Sent, ResponseMSG: "+String.valueOf(conn.getResponseMessage()));
This is a printout of the message I get back from the server:
{null=[HTTP/1.1 400 Bad Request], Content-Length=[42], Content-Type=[text/plain], X-Android-Received-Millis=[1449836192887], X-Android-Response-Source=[NETWORK 400], X-Android-Sent-Millis=[1449836192719]}
NOTE: I coded this based on the best of my knowledge and after examining related posts here on StartOverflow, the whole code is inside the doInBackground method of an AsyncTask so lets focus here. I hope can help me!! Thanks.
After much fiddling with the code, I found a way to upload a wav file with URLConnection, and using multipartentity. Here is the code, enjoy:
public int uploadWav(String sourceFileUri) {
String wavpath=Environment.getExternalStorageDirectory().getAbsolutePath()+"/myAppFolder/"+StorageUtils.AUDIO_FILE_NAME+".wav";
String filename=wavpath;
HttpURLConnection conn = null;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "------------------------afb19f4aeefb356c";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
File sourceFile = new File(fileName);
Log.e("joshtag", "Uploading: sourcefileURI, "+fileName);
if (!sourceFile.isFile()) {
Log.e("uploadFile", "Source File not exist :"+wavpath);//FullPath);
return 0; //RETURN #1
}
else{
try{
Log.v("joshtag","UPLOADING .WAV FILE");
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(SERVER_URL);
Log.v("joshtag","UL URL: "+url.toString());
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy s
conn.setRequestMethod("POST");
// conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("file", sourceFile.getName());
//so on and so forth...
//conn.setRequestProperty("param", "value");
conn.setRequestProperty("connection", "close");
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + sourceFile.getName() + "\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
Log.i("joshtag","->");
}
Log.i("joshtag","->->");
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
conn.connect();
Log.i("joshtag","->->->");
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
Log.i("joshtag","->->->->");
String serverResponseMessage = conn.getResponseMessage().toString();
Log.i("joshtag","->->->->->");
Log.i("joshtag", "HTTP Response is : " + serverResponseMessage + ": " + serverResponseCode);
// ------------------ read the SERVER RESPONSE
DataInputStream inStream;
String str="";
String response="";
try {
Log.i("joshtag","->->->->->->");
inStream = new DataInputStream(conn.getInputStream());
while ((str = inStream.readLine()) != null) {
Log.e("joshtag", "SOF Server Response" + str);
response=str;
}
inStream.close();
}
catch (IOException ioex) {
Log.e("joshtag", "SOF error: " + ioex.getMessage(), ioex);
}
conn.disconnect();
conn=null;
//close the streams //
fileInputStream.close();
dos.flush();
dos.close();
if(serverResponseCode == 201){
loge("*** SERVER RESPONSE: 201"+response);
}//END IF Response code 201
// conn.disconnect();
}//END TRY - FILE READ
catch (MalformedURLException ex) {
ex.printStackTrace();
Log.e("joshtag", "UL error: " + ex.getMessage(), ex);
} //CATCH - URL Exception
catch (Exception e) {
e.printStackTrace();
Log.e("Upload file to server Exception", "Exception : "+ e.getMessage(), e);
}
return serverResponseCode; //after try
}//END ELSE, if file exists.
}

showing a progress bar during file upload

I've got an async task that is supposed to show progress during a file upload. Everything is working except that it looks like it finishes the file upload really really fast, and then it just sits there at 100% waiting.
I traced this down to
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"Filedata\";filename=\"" + pathToOurFile + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
long totalBytesWritten = 0;
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
outputStream.flush();
if (mCancel) { throw new CancelException(); }
totalBytesWritten += bufferSize;
if (mProgressDialog != null) {
mProgressDialog.setProgress(Integer.valueOf((int) (totalBytesWritten / 1024L)));
}
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
int serverResponseCode = connection.getResponseCode();
What I noticed is that there's no real delay until the very last line where it's getting the response code. I think what's happening is that the data is getting buffered so it looks like it has uploaded it, but hasn't really - it has just buffered it. Then when i get to the getResponseCode() call, it has no choice but to finish the upload to get the upload status. is there any way to make it actually upload along the way so i can get a reasonable progress?
This is how HTTP Post is designed to work so do not expect it to give you progress details.
You can use one of the several file uploader components available in the market. They internally use flash or silverlight or iframes to show the progress.
http://dhtmlx.com/docs/products/dhtmlxVault/index.shtml
http://www.element-it.com/multiple-file-upload/flash-uploader.aspx
You will find many such others if you google a bit.
They internally use raw IO instead of http post to handle multiple files and progress notification. Yahoo and Google also uses such techniques for making attachments to mail.
If you are really feeling adventurous, you can recreate the wheel - i.e. write your own component.
Edit:
Please specify if you want to do this in a windows desktop application or a web application.
You can use Progress Dialog class as follows,
ProgressDialog progDailog = ProgressDialog.show(this,"Uploading", "Uploading File....",true,true);
new Thread ( new Runnable()
{
public void run()
{
// your loading code goes here
}
}).start();
Handler progressHandler = new Handler()
{
public void handleMessage(Message msg1)
{
progDailog.dismiss();
}
}
You can try using a AsyncTask ...
create a progress dialog in onPreExecute method and dismiss the dialog in onPostExecute method..
Keep the upload method in doInBackground()
example :
public class ProgressTask extends AsyncTask<String, Void, Boolean> {
public ProgressTask(ListActivity activity) {
this.activity = activity;
dialog = new ProgressDialog(context);
}
/** progress dialog to show user that the backup is processing. */
private ProgressDialog dialog;
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
protected Boolean doInBackground(final String... args) {
// your upload code
return true;
}
}
}
HttpURLConnection.setFixedLengthStreamingMode(...) did the trick!
You can do like:
try { // open a URL connection to the Servlet
FileInputStream fileInputStream = new FileInputStream(
sourceFile);
URL url = new URL("http://10.0.2.2:9090/plugins/myplugin/upload");
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("uploadedfile", filename);
// conn.setFixedLengthStreamingMode(1024);
// conn.setChunkedStreamingMode(1);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ filename + "\"" + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = (int) sourceFile.length()/200;//suppose you want to write file in 200 chunks
buffer = new byte[bufferSize];
int sentBytes=0;
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
// Update progress dialog
sentBytes += bufferSize;
publishProgress((int)(sentBytes * 100 / bytesAvailable));
bytesAvailable = fileInputStream.available();
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
// close streams
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

Connection to apache server refused

i know that there are similar questions on Stackoverflow, but they did not solve my problem. I want to upload a file from android to a local apache server, but gain a 'connection refused' error.
I'am using a physical device with Android 3.2 and MAMP on Mac OS X Lion (Apache on Port 80). I also added the INTERNET permission to the manifest.
Here is the code:
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(new File(
"/mnt/sdcard/somefile.xml"));
} catch (FileNotFoundException e) {
...
}
URL url = null;
try {
url = new URL("http://192.168.x.xxx:80/index.php");
} catch (MalformedURLException e) {
...
}
try {
// Open a HTTP connection to the URL
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: post-data; name=uploadedfile;filename="
+ SOMEFILE + "" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1000;
// int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bytesAvailable];
// read file and write it into form...
int bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
while (bytesRead > 0) {
dos.write(buffer, 0, bytesAvailable);
bytesAvailable = fileInputStream.available();
bytesAvailable = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// close streams
fileInputStream.close();
dos.flush();
dos.close();
} catch (IOException e) {
...
}
The Exception:
07-24 14:48:43.280: E/App(5802): failed to upload file '/mnt/sdcard/somefile.xml' to
server 'http://192.168.x.xxx:80/index.php'
07-24 14:48:43.280: E/App(5802): java.net.ConnectException: /192.168.x.xxx:80 -
Connection refused
Do you have the firewall enable and running on your Mac?
The best way (IMHO) to determine whether port 80 really is open is to run NMap (or the gui Zenmap) on another machine on the local network against the target address(es).
If it's just your desktop machine and your Android device, you could try browsing to http://192.168.x.x to see if the Apache server is giving a response.
the code seems to be ok. The emulator can connect without problems. There was a problem with the router firewall

Android-Django Image upload

I am trying to upload image with android as frontend and django as backend.
The model:
class Photo(models.Model):
title = models.CharField(max_length=255,blank=True)
photo = models.FileField(upload_to='photos')
description = models.TextField(blank=True)
uploaded = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'media_photos'
def __unicode__(self):
return '%s' % self.title
The view to url url(r'^photos/upload/$','upload_photo'):
def upload_photo(request):
form=PhotoForm(request.POST,request.FILES)
if request.method=='POST':
if form.is_valid():
image = request.FILES['photo']
title1 =''
new_image = Photo(title=title1,photo=image,description='')
new_image.save()
response_data=[{"success": "1"}]
return HttpResponse(simplejson.dumps(response_data), mimetype='application/json')
now i am trying to access the view here from android.
So now my android side code to upload image is:
public void doFileUpload(String path){
HttpURLConnection conn = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
String lineEnd = "\r\n";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
String urlString = "http://"; // server ip
try
{
//------------------ CLIENT REQUEST
FileInputStream fileInputStream = new FileInputStream(new File(path) );
// open a URL connection to the Servlet
URL url = new URL(urlString);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+" ");
dos = new DataOutputStream( conn.getOutputStream() );
dos.writeBytes(lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + path + "\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(lineEnd);
// close streams
Log.e("Debug","File is written");
fileInputStream.close();
dos.flush();
dos.close();
}
catch (MalformedURLException ex)
{
Log.e("Debug", "error: " + ex.getMessage(), ex);
}
catch (IOException ioe)
{
Log.e("Debug", "error: " + ioe.getMessage(), ioe);
}
//------------------ read the SERVER RESPONSE
try {
inStream = new DataInputStream ( conn.getInputStream() );
String str;
while (( str = inStream.readLine()) != null)
{
Log.e("Debug","Server Response "+str);
}
inStream.close();
}
catch (IOException ioex){
Log.e("Debug", "error: " + ioex.getMessage(), ioex);
}
}
}
but it gives me an error:
E/Debug(590): error: java.net.URISyntaxException: Authority expected at index 7: http://
Should be urlString = "http://192.168.1.2/photos/upload";
But then if it doesn't work, you'll get a different error, and we'll probably need that error to answer further.
Also, it looks like you don't have a real boundary string set and you aren't using it correctly.
Have a look here. Notice how he uses a unique boundary string and writes it to the output stream?
Even after you overcome these difficulties, you'll run afoul of Django's requirement that you supply a csrfmiddlewaretoken with your POST parameters. And I don't see how you can obtain that on an Android device; by design that token is there to prevent calling Django backend code (i.e. a "view") from anything other than a Django frontend (i.e. a "template"). I.e. it's designed to thwart doing exactly what you're trying to do.
You could disable the csrf feature on a particular view -- use the "#csrf_exempt" decorator. And then you can decide if you care enough about security, to work out a substitute of your own for what the csrf thing gives you.
Or, instead of uploading a picture from an Android app, write a web app to upload a picture, and have your Django project serve up that web app. Your Android app could launch the browser (as an Intent) and point it at that web app. Here's some code that'll do that: https://simpleisbetterthancomplex.com/tutorial/2016/08/01/how-to-upload-files-with-django.html (It won't win any beauty contests, but it does work.)

Categories

Resources