Sending MultipartEntity using HttpURLConnection - java

using the below code, i am able to send a large file to the server, but i cant seem to find out how send a text with the file.(send the file plus extra data(username, password..) for example). and also receive it at the server side.
FileInputStream fileInputStream = new FileInputStream(new File(
pathToOurFile));
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setChunkedStreamingMode(1024);
// 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);
String connstr = null;
connstr = "Content-Disposition: form-data; name=\"uploadedVideos\";filename=\""
+ pathToOurFile + "\"" + lineEnd;
outputStream.writeBytes(connstr);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
try {
while (bytesRead > 0) {
try {
outputStream.write(buffer, 0, bufferSize);
} catch (OutOfMemoryError e) {
e.printStackTrace();
response = "outofmemoryerror";
return response;
}
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
} catch (Exception e) {
e.printStackTrace();
response = "error";
return response;
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens
+ lineEnd);
fileInputStream.close();
outputStream.flush();
outputStream.close();
the server part:
HttpPostedFile file = HttpContext.Current.Request.Files[0];
string fname = Path.GetFileName(file.FileName);
file.SaveAs(Server.MapPath(Path.Combine("~/UploadedVideos/" + Date + "/", fname)));
please any help will be appreciated.
i know i can do this using HttpClient, but its not working for me in case of large files so i want to use this way.

Use this,
private static String multipost(String urlString, MultipartEntity reqEntity) {
try {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.addRequestProperty("Content-length", reqEntity.getContentLength()+"");
conn.addRequestProperty(reqEntity.getContentType().getName(), reqEntity.getContentType().getValue());
OutputStream os = conn.getOutputStream();
reqEntity.writeTo(conn.getOutputStream());
os.close();
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
return readStream(conn.getInputStream());
}
} catch (Exception e) {
Log.e("MainActivity", "multipart post error " + e + "(" + urlString + ")");
}
return null;
}
private static String readStream(InputStream in) {
BufferedReader reader = null;
StringBuilder builder = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return builder.toString();
}
and here you can set File, username and password as like below using MultipartEntiry.
private void uploadMultipartData() throws UnsupportedEncodingException {
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("fileToUpload", new FileBody(uploadFile));
reqEntity.addPart("uname", new StringBody("MyUserName"));
reqEntity.addPart("pwd", new StringBody("MyPassword"));
String response = multipost(server_url, reqEntity);
Log.d("MainActivity", "Response :"+response);
}
Note: You need to add httpmime jar in your libs folder.

this is my working code, i recalled copying this from somewhere, cant recall it...
package my.com.myapp.utils;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/**
* This utility class provides an abstraction layer for sending multipart HTTP
* POST requests to a web server.
* #author www.codejava.net
*
*/
public class MultipartUtil {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
protected String charset;
protected OutputStream outputStream;
protected PrintWriter writer;
public boolean cancel = false;
protected boolean last_item_is_file = false;
public static String LOG_TAG = "MultipartUtil";
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
* #param requestURL
* #param charset
* #throws IOException
*/
public MultipartUtil(String requestURL, String charset, Boolean send_auth)
throws IOException {
this.charset = charset;
// creates a unique boundary based on time stamp
boundary = "===" + System.currentTimeMillis() + "===";
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
httpConn.setRequestProperty("User-Agent", "Android submit");
//addHeaderField("lang", AppConfig.getInstance().language);
//addHeaderField("country", AppConfig.getInstance().country);
//User user = AppConfig.getInstance().get_user();
/*
if (send_auth && user != null && user.authentication_token != null && !user.authentication_token.equalsIgnoreCase("")) {
Log.i(LOG_TAG, "user token: "+user.authentication_token);
addHeaderField("X-User-Email", user.email);
addHeaderField("X-User-Token", user.authentication_token);
} else {
Log.i(LOG_TAG, "not auth / not logged in");
}
*/
// httpConn.setRequestProperty("Test", "Bonjour");
}
public PrintWriter setup_writer() throws IOException {
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
return writer;
}
/**
* Adds a form field to the request
* #param name field name
* #param value field value
*/
public void addFormField(String name, String value) {
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
.append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=" + charset).append(
LINE_FEED);
writer.append(LINE_FEED);
writer.append(value).append(LINE_FEED);
writer.flush();
last_item_is_file = false;
}
/**
* Adds a upload file section to the request
* #param fieldName name attribute in <input type="file" name="..." />
* #param uploadFile a File to be uploaded
* #throws IOException
*/
public void addFilePart(String fieldName, File uploadFile)
throws IOException {
String fileName = uploadFile.getName();
writer.append("--" + boundary).append(LINE_FEED);
writer.append(
"Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
writer.append(
"Content-Type: "
+ URLConnection.guessContentTypeFromName(fileName))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while (!cancel && (bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
if (cancel) {
writer.close();
return;
}
writer.append(LINE_FEED);
writer.flush();
last_item_is_file = true;
}
public void addFileStreamPart(String fieldName, String fileName, InputStream inputStream)
throws IOException {
writer.append("--" + boundary).append(LINE_FEED);
writer.append(
"Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
writer.append(
"Content-Type: "
+ URLConnection.guessContentTypeFromName(fileName))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while (!cancel && (bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
if (cancel) {
writer.close();
return;
}
writer.append(LINE_FEED);
writer.flush();
last_item_is_file = true;
}
/**
* Adds a header field to the request.
* #param name - name of the header field
* #param value - value of the header field
*/
public void addHeaderField(String name, String value) {
httpConn.setRequestProperty(name, value);
//writer.append(name + ": " + value).append(LINE_FEED).flush();
//addFormField("headers["+name+"]", value);
//writer.append(name + ": " + value).append(LINE_FEED).flush();
}
public HttpURLConnection finish() throws IOException {
if (last_item_is_file)
writer.append(LINE_FEED).flush();
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close();
return httpConn;
}
}

Related

How to retrieve multipart/form-data from HttpServletRequest in Struts2

I am trying to retrieve the sent data on post request from the client android app, but unfortunately i am not getting multipart data from request, the code just returns null value.
Client side code: option 1:
private String uploadFile(String filePath) {
Log.d(TAG, "uploadFile: called");
HttpURLConnection connection;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1024 * 1024;
File uploadFile = new File(filePath);
if(!uploadFile.isFile()) {
mDownloadStatus = DownloadStatus.NOT_INITIALIZED;
Log.d(TAG, "uploadFile: file not found");
return null;
}
try {
FileInputStream fileInputStream = new FileInputStream(uploadFile);
mDownloadStatus = DownloadStatus.PROCESSING;
URL url = new URL(POSTUPLOADFILE_URL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setRequestProperty("ENCTYPE", "multipart/form-data");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
connection.setRequestProperty("uploaded_file", filePath);
connection.connect();
dos = new DataOutputStream(connection.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""+ filePath + "\"" + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
Log.d(TAG, "uploadFile: bytesAvailable: " + bytesAvailable);
Log.d(TAG, "uploadFile: initial available: " + bytesAvailable);
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
Log.d(TAG, "uploadFile: initial: " + bytesRead);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
Log.d(TAG, "uploadFile: bytesRead: " + bytesRead);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
int responseCode = connection.getResponseCode();
Log.d(TAG, "uploadFile: respnse code: " + responseCode);
fileInputStream.close();
dos.flush();
dos.close();
// receive upload link from server
int ch;
StringBuilder sb = new StringBuilder();
InputStream is = connection.getInputStream();
while ((ch = is.read()) != -1) {
sb.append((char)ch);
}
is.close();
mDownloadStatus = DownloadStatus.OK;
return sb.toString();
} catch (IOException e) {
Log.e(TAG, "uploadFile: IOException: " + e);
}
mDownloadStatus = DownloadStatus.FAILED_OR_EMPTY;
return null;
}
client side code: option 2:
private String uploadFile(String filePath) {
File uploadFile = new File(filePath);
if(!uploadFile.isFile()) {
mDownloadStatus = DownloadStatus.NOT_INITIALIZED;
Log.d(TAG, "uploadFile: file not found");
return null;
}
try {
mDownloadStatus = DownloadStatus.PROCESSING;
HttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(POSTUPLOADFILE_URL);
FileBody fileBody = new FileBody(new File(filePath));
StringBody title = new StringBody("Filename: " + filePath, ContentType.DEFAULT_TEXT);
StringBody description = new StringBody("This is a post file", ContentType.DEFAULT_TEXT);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("file", fileBody);
builder.addPart("title", title);
builder.addPart("description", description);
HttpEntity entity = builder.build();
post.setEntity(entity);
Log.d(TAG, "uploadFile: executing request: ");
HttpResponse response = httpClient.execute(post);
Log.d(TAG, "uploadFile: response status: " + response.getCode());
Log.d(TAG, "uploadFile: " + response.toString());
} catch (IOException e) {
Log.e(TAG, "uploadFile: IOException" + e.getMessage(), e);
}
mDownloadStatus = DownloadStatus.FAILED_OR_EMPTY;
return null;
}
Server side code:
public String uploadFile() throws IOException, ServletException, FileUploadException {
System.out.println("upload file on postAction: called");
HttpServletRequest request = ServletActionContext.getRequest();
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
System.out.println("items size: " + items.size());
for(FileItem item: items) {
if(item.isFormField()) {
// get file
} else {
}
}
return null;
}
PROBLEM: there is multipart data on the request,because request.contentLength is reasonable size, but list size just returns 0, so now I can't get uploaded file. How can I solve to get multipart data from the request?
I figured out the solution for the problem by using 'MultipartRequestWrapper'
public String uploadFile() throws IOException, ServletException, FileUploadException {
System.out.println("upload file on postAction: called");
HttpServletRequest request = ServletActionContext.getRequest();
MultiPartRequestWrapper multipartRequest = ((MultiPartRequestWrapper)ServletActionContext.getRequest());
Enumeration<String> fileParameterNames = multipartRequest.getFileParameterNames();
if(fileParameterNames.hasMoreElements()) {
String inputValue = fileParameterNames.nextElement();
System.out.println("inputValue: " + inputValue);
String[] localFileNames = multipartRequest.getFileNames(inputValue);
for (String fn : localFileNames) {
System.out.println("local filename = " + fn);
}
File[] files = multipartRequest.getFiles(inputValue);
for (File cf : files) {
File destFile = new File(POST_FILE_DESTINATION + localFileNames[0]);
FileUtils.copyFile(cf, destFile);
FileUtils.deleteQuietly(cf);
}
}
return null
}
the reference here

How can I send multiple files and texts simultaneously to server over http protocol in Android?

I wanna send a file and some variables to server, to insert in a table in a android app using AsyncTask. here is my java code:
try {
URL url = new URL(upLoadServerUri);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
OutputStream outputStream = httpURLConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream,"UTF-8"));
String post_data= URLEncoder.encode("username" , "UTF-8")+"="+URLEncoder.encode(username,"UTF-8");
bufferedWriter.write(post_data);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "iso-8859-1"));
result="";
String line="";
while ((line=bufferedReader.readLine()) != null){
result += line;
}
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
}catch (MalformedURLException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
try {
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(upLoadServerUri);
// 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.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE",
"multipart/form-data");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("bill", sourceFileUri);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"bill\";filename=\""
+ sourceFileUri + "\"" + 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)
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn
.getResponseMessage();
// close the streams //
fileInputStream.close();
dos.flush();
dos.close();
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
And PHP code:
if (is_uploaded_file($_FILES['bill']['tmp_name'])) {
$uploads_dir = './sensorLog/$user_name';
$tmp_name = $_FILES['bill']['tmp_name'];
$pic_name = $_FILES['bill']['name'];
move_uploaded_file($tmp_name, $uploads_dir.$pic_name);
if($conn->query($mysql_qry) === TRUE) {
echo "upload and update successful";
}else { echo "Error" . $mysql_qry . "<br>" . $conn->error;}
}else{ echo "File not uploaded successfully."; }
I use two httpconnection object and I think this is the problem. How can I send variables and file simultaneously? this code upload the file to server, but the table isn't updated. it just add an empty row:(.
Use this class to send multipart requests:
class MultipartUtility {
public HttpURLConnection httpConn;
public OutputStream request;//if you wanna send anything out of ordinary use this;
private final String boundary = "*****";//alter this as you wish
private final String crlf = "\r\n";
private final String twoHyphens = "--";
public MultipartUtility(String requestURL)
throws IOException {
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
//alter this part if you wanna set any headers or something
httpConn.setRequestProperty("Connection", "Keep-Alive");
httpConn.setRequestProperty("Cache-Control", "no-cache");
httpConn.setRequestProperty(
"Content-Type", "multipart/form-data;boundary=" + this.boundary);
request = httpConn.getOutputStream();
}
//or add some other constructor to better fit your needs; like set cookies and stuff
public void addFormField(String name, String value)throws IOException {
request.write(( this.twoHyphens + this.boundary + this.crlf).getBytes());
request.write(("Content-Disposition: form-data; name=\"" + name + "\""+ this.crlf).getBytes());
request.write(this.crlf.getBytes());
request.write((value).getBytes());
request.write(this.crlf.getBytes());
request.flush();
}
public void addFilePart(String fieldName, File uploadFile)
throws IOException,Exception {
if(uploadFile.isDirectory())throw new Exception("for real? what do you expect to happen?");
request.write((this.twoHyphens + this.boundary + this.crlf).getBytes());
request.write(("Content-Disposition: form-data; name=\"" +
fieldName + "\";filename=\"" +
uploadFile.getName()+ "\"" + this.crlf).getBytes());
request.write(this.crlf.getBytes());
InputStream is=new FileInputStream(uploadFile);
byte[] bytes = new byte[1024];
int c=is.read(bytes);
while(c>0){
request.write(bytes,0,c);
c=is.read(bytes);
}
request.write(this.crlf.getBytes());
request.flush();
is.close();
}
public String finish() throws IOException {
String response ="";
request.write((this.twoHyphens + this.boundary +
this.twoHyphens + this.crlf).getBytes());
request.flush();
request.close();
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
InputStream responseStream = httpConn.getInputStream();
byte[] b=new byte[1024];
int c=responseStream.read(b);
while(c>0){
response=response+new String(b,0,c);
c=responseStream.read(b);
}
responseStream.close();
} else {
httpConn.disconnect();
throw new IOException("Server returned non-OK status: " + status);
}
httpConn.disconnect();
return response;
}
public InputStream finish_with_inputstream()throws Exception{
request.write((this.twoHyphens + this.boundary +
this.twoHyphens + this.crlf).getBytes());
request.flush();
request.close();
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
return httpConn.getInputStream();
} else {
throw new IOException("Server returned non-OK status: " + status);
}
}
}
example:
try{
MultipartUtility m=new MultipartUtility("https://mydomain");//now add you different data parts;
m.addFilePart("file_part",new File("some_file_location"));
m.addFormField("value_name","value");
//call either of the below methods based on what you need; do not call both!
String result=m.finish();//call this if the response is a small text
InputStream is=m.finish_with_inputstream(); //call this if the response is huge and not fitting in memory; don't forget to disconnect the connection afterwards;
} catch (IOException e) {
e.printStackTrace();
}
now you can handle all these data in one request on the php side:
$value=$_POST["value_name"];
$file_data=file_get_contents($_FILES["file_part"]["tmp_name"])
so for you situation it would be like below:
try{
MultipartUtility m=new MultipartUtility("https://mydomain");
m.addFilePart("bill",new File(sourceFile));
m.addFormField(URLEncoder.encode("username" , "UTF-8"),URLEncoder.encode(username,"UTF-8"));
String result=m.finish();
} catch (Exception e) {
e.printStackTrace();
}

Why is this POST request through HttpURLConnection throwing a FileNotFoundException?

Update 3: I tried to execute this request against requestb.in insteaad of the Blobstore URL and the same exception occured, so this looks like a problem with my upload method using HttpURLConnection and not a Blobstore specific issue.
Update 2: Added code for creating the upload URL method at the bottom
Update 1: Added code and exact exception below the question. Hope the situation is clearer now.
Files are getting uploaded to the Blobstore using a POST request to the URL provided by the createUploadURL() method. However, App Engine still responds with a FileNotFoundException to the upload requests complaining that a file was not found at https://<app-id>.appspot.com/_ah/upload/<long-random-string>
What could be going on here?
Upload Code:
try {
MultipartUtility multipartUtility = new MultipartUtility(blobUploadURL, "UTF-8",writeListener);
multipartUtility.addFormField("key_name", keyName);
multipartUtility.addFilePart("file", fileName, is);
multipartUtility.finish();
} catch (IOException e) {
}
MultipartUtility Class:
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer;
private WriteListener listener;
public static interface WriteListener{
void transferred(long num);
}
public MultipartUtility(String requestURL, String charset,WriteListener listener)
throws IOException {
this.charset = charset;
// creates a unique boundary based on time stamp
boundary = "===" + System.currentTimeMillis() + "===";
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
httpConn.setChunkedStreamingMode(-1);
outputStream=httpConn.getOutputStream();
this.listener=listener;
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
}
public void addFormField(String name, String value) {
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
.append(LINE_FEED);
writer.append("Content-Type: text/plain; charset=" + charset).append(
LINE_FEED);
writer.append(LINE_FEED);
writer.append(value).append(LINE_FEED);
writer.flush();
}
public void addFilePart(String fieldName, String fileName, InputStream is)
throws IOException {
//String fileName = uploadFile.getName();
writer.append("--" + boundary).append(LINE_FEED);
writer.append(
"Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
writer.append(
"Content-Type: "
+ URLConnection.guessContentTypeFromName(fileName))
.append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = is.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
writer.append(LINE_FEED);
writer.flush();
}
public void addHeaderField(String name, String value) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
}
public List<String> finish() throws IOException {
List<String> response = new ArrayList<String>();
writer.append(LINE_FEED).flush();
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
// checks server's status code first
int status = httpConn.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
throw new IOException("Server returned non-OK status: " + status);
}
reader.close();
httpConn.disconnect();
return response;
}
}
IO Exception caught when the upload request is executed:
java.io.FileNotFoundException: https://<app-id>.appspot.com/_ah/upload/<random-long-string>
Code for creating the Blobstore upload URL: (Note that I can see the uploaded files in Blobstore and even confirm that the blob handler servlet is also getting the key of the uploaded blob despite this exception.)
BlobstoreService bs = BlobstoreServiceFactory.getBlobstoreService();
String blobUploadURL = bs.createUploadUrl("/save/blob");

Uploading Multipart-form-data to php

I would like upload any data (Username, Description,..) and a photo from my Android-App to my Server (PHP-Script).
By searching for this i found a solution: How to take a photo and send to HTTP POST request with Android?
By click on my send button, the upload-process starts and the php-script works but the $_POST -Vars are empty? Can anybody help me? My request-code:
[...]
case R.id.btnSend:
String strName = tName.getText().toString();
String strEmail = tEmail.getText().toString();
String strDatum = tDatum.getText().toString();
String strBeschreibung = tBeschreibung.getText().toString();
nvPairs = new ArrayList<NameValuePair>(2);
nvPairs.add(new BasicNameValuePair("sender", "AndoidApp"));
nvPairs.add(new BasicNameValuePair("name", strName));
nvPairs.add(new BasicNameValuePair("email", strEmail));
nvPairs.add(new BasicNameValuePair("datum", strDatum));
nvPairs.add(new BasicNameValuePair("beschreibung", strBeschreibung));
nvPairs.add(new BasicNameValuePair("bild", bmpUrl));
new UploadTask().execute();
}
[...]
private class UploadTask extends AsyncTask<Void, Void, List<String>> {
#Override
protected List<String> doInBackground(Void... params) {
String response = "";
try {
response = new MultipartServer().postData(new URL(postUrl), nvPairs);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
On the MultipartServer-Code i changed the line:
if ((avatarName = pair.getName()).equals("avatar")) {
avatarPath = pair.getValue();
}
to this:
if ((avatarName = pair.getName()).equals("bild")) {
avatarPath = pair.getValue();
}
And the Variables "bmpUrl" and "postUrl" are set correctly at an another line in my code.
Thanks for your help! I found an solution for the problem. The problem was at the Script from How to take a photo and send to HTTP POST request with Android?
I changed it to this:
public class MultipartServer {
private static final String TAG = "MultipartServer";
private static final String crlf = "\r\n";
private static final String twoHyphens = "--";
private static final String boundary = "AaB03x"; //*****
private String avatarName = null;
private String avatarPath = null;
public String postData(URL url, List<NameValuePair> nameValuePairs) throws IOException {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Cache-Control", "no-cache");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
FileInputStream inputStream;
OutputStream outputStream = connection.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
for (NameValuePair pair : nameValuePairs) {
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(twoHyphens + boundary + crlf);
dataOutputStream.writeBytes(
"Content-Disposition: form-data; name=\""
+ URLEncoder.encode(pair.getName(), "UTF-8")
+ "\";" + crlf);
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(URLEncoder.encode(pair.getValue(), "UTF-8"));
if (pair.getName().equals("bild")) {
avatarName = pair.getName();
avatarPath = pair.getValue();
}
}
// Write Avatar (if any)
if (avatarName != null && avatarPath != null) {
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(twoHyphens + boundary + crlf);
dataOutputStream
.writeBytes("Content-Disposition: form-data; name=\""
+ avatarName + "\";filename=\""
+ new File(avatarPath).getName() + "\";" + crlf);
dataOutputStream.writeBytes(crlf);
inputStream = new FileInputStream(avatarPath);
byte[] data = new byte[1024];
int read;
while ((read = inputStream.read(data)) != -1)
dataOutputStream.write(data, 0, read);
inputStream.close();
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
}
dataOutputStream.flush();
dataOutputStream.close();
String responseMessage = connection.getResponseMessage();
Log.d(TAG, responseMessage);
InputStream in = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(in, "UTF-8"));
StringBuilder response = new StringBuilder();
char[] b = new char[512];
int read;
while ((read = bufferedReader.read(b)) != -1) {
response.append(b, 0, read);
}
connection.disconnect();
Log.d(TAG, response.toString());
return response.toString();
}
}

Posting a multipart request with image in Android?

I am trying to post a JSON representation of my object and an optional image to my Spring backend. However, I am having major trouble posting a request with an image. I have managed to post the first part to the server; the JSON object. However when I try to add a second part which is an image captured by the user nothing happens. I don't see any stacktraces.
What am I doing wrong and how do I post an image along the request. This is what I have...
String boundary = UUID.randomUUID().toString();
String twoHyphens = "--";
String attachmentName = "data";
String crlf = "\r\n";
try {
URI uri = new URI("http://myappserver.com/app");
HttpURLConnection urlConnection = (HttpURLConnection) uri.toURL().openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream dos = new DataOutputStream(urlConnection.getOutputStream());
InputStream inputStream = context.getContentResolver().openInputStream(question.getUri());
// FIRST PART; A JSON object
dos.writeBytes(twoHyphens + boundary);
dos.writeBytes(crlf);
dos.writeBytes("Content-Type: application/json");
dos.writeBytes(crlf);
dos.writeBytes("Content-Disposition: form-data; name=\"data\"");
dos.writeBytes(crlf);
dos.writeBytes(crlf);
dos.writeBytes(jsonEntity);
dos.writeBytes(crlf);
// SECOND PART; A image..
dos.writeBytes(twoHyphens + boundary);
dos.writeBytes(crlf);
dos.writeBytes("Content-Type: image/jpg");
dos.writeBytes(crlf);
dos.writeBytes("Content-Disposition: form-data; name=\"image\"");
dos.writeBytes(crlf);
dos.writeBytes(crlf);
// Something must be done here. I guess I must encode it to Base64 here.
// How can I avoid loading the whole image at once so I don't get out of memory errors.
dos.writeBytes(crlf);
dos.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
dos.close();
} catch (Exception e) {
}
The code illustrates how to send a file (here it is pdf). Go through it, it will be helpful for you to debug your code.
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
FileInputStream fileInputStream = new FileInputStream(file);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"attachment_0\";filename=\"" + file.getName() + "\"" + lineEnd);
dos.writeBytes("Content-Type: text/pdf" + lineEnd);
dos.writeBytes("Content-Length: " + file.length() + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
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);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
fileInputStream.close();
}
//for sending a parameter, see below, key is the key of the webservice parameter.
dos.writeBytes("Content-Disposition: form-data; name=\""+key+"\"" + lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(requestData.get(key).toString() + lineEnd);
Below is my implementation of a MULTIPART form data upload using HttpURLConnection class. This class employs a Dynamic usage so that multiple request can be invoked at a time with different sets of data.
NB: I'm breaking the json part into individual text forms inorder to maintain consistency with my server. You may modify it to match your servers requirement.
public class WebConnector {
String boundary = "-------------" + System.currentTimeMillis();
private static final String LINE_FEED = "\r\n";
private static final String TWO_HYPHENS = "--";
private StringBuilder url;
private String protocol;
private HashMap<String, String> params;
private JSONObject postData;
private List<String> fileList;
private int count = 0;
private DataOutputStream dos;
public WebConnector(StringBuilder url, String protocol,
HashMap<String, String> params, JSONObject postData) {
super();
this.url = url;
this.protocol = protocol;
this.params = params;
this.postData = postData;
createServiceUrl();
}
public WebConnector(StringBuilder url, String protocol,
HashMap<String, String> params, JSONObject postData, List<String> fileList) {
super();
this.url = url;
this.protocol = protocol;
this.params = params;
this.postData = postData;
this.fileList = fileList;
createServiceUrl();
}
public String connectToMULTIPART_POST_service(String postName) {
System.out.println(">>>>>>>>>url : " + url);
StringBuilder stringBuilder = new StringBuilder();
String strResponse = "";
InputStream inputStream = null;
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) new URL(url.toString()).openConnection();
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestProperty("Connection", "close");
urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 ( compatible ) ");
urlConnection.setRequestProperty("Authorization", "Bearer " + Config.getConfigInstance().getAccessToken());
urlConnection.setRequestProperty("Content-type", "multipart/form-data; boundary=" + boundary);
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.setChunkedStreamingMode(1024);
urlConnection.setRequestMethod("POST");
dos = new DataOutputStream(urlConnection.getOutputStream());
Iterator<String> keys = postData.keys();
while (keys.hasNext()) {
try {
String id = String.valueOf(keys.next());
addFormField(id, "" + postData.get(id));
System.out.println(id + " : " + postData.get(id));
} catch (JSONException e) {
e.printStackTrace();
}
}
try {
dos.writeBytes(LINE_FEED);
dos.flush();
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
if (fileList != null && fileList.size() > 0 && !fileList.isEmpty()) {
for (int i = 0; i < fileList.size(); i++) {
File file = new File(fileList.get(i));
if (file != null) ;
addFilePart("photos[" + i + "][image]", file);
}
}
// forming th java.net.URL object
build();
urlConnection.connect();
int statusCode = 0;
try {
urlConnection.connect();
statusCode = urlConnection.getResponseCode();
} catch (EOFException e1) {
if (count < 5) {
urlConnection.disconnect();
count++;
String temp = connectToMULTIPART_POST_service(postName);
if (temp != null && !temp.equals("")) {
return temp;
}
}
} catch (IOException e) {
e.printStackTrace();
}
// 200 represents HTTP OK
if (statusCode == HttpURLConnection.HTTP_OK) {
inputStream = new BufferedInputStream(urlConnection.getInputStream());
strResponse = readStream(inputStream);
} else {
System.out.println(urlConnection.getResponseMessage());
inputStream = new BufferedInputStream(urlConnection.getInputStream());
strResponse = readStream(inputStream);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != inputStream)
inputStream.close();
} catch (IOException e) {
}
}
return strResponse;
}
public void addFormField(String fieldName, String value) {
try {
dos.writeBytes(TWO_HYPHENS + boundary + LINE_FEED);
dos.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\"" + LINE_FEED + LINE_FEED/*+ value + LINE_FEED*/);
/*dos.writeBytes("Content-Type: text/plain; charset=UTF-8" + LINE_FEED);*/
dos.writeBytes(value + LINE_FEED);
} catch (IOException e) {
e.printStackTrace();
}
}
public void addFilePart(String fieldName, File uploadFile) {
try {
dos.writeBytes(TWO_HYPHENS + boundary + LINE_FEED);
dos.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\";filename=\"" + uploadFile.getName() + "\"" + LINE_FEED);
dos.writeBytes(LINE_FEED);
FileInputStream fStream = new FileInputStream(uploadFile);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = -1;
while ((length = fStream.read(buffer)) != -1) {
dos.write(buffer, 0, length);
}
dos.writeBytes(LINE_FEED);
dos.writeBytes(TWO_HYPHENS + boundary + TWO_HYPHENS + LINE_FEED);
/* close streams */
fStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void addHeaderField(String name, String value) {
try {
dos.writeBytes(name + ": " + value + LINE_FEED);
} catch (IOException e) {
e.printStackTrace();
}
}
public void build() {
try {
dos.writeBytes(LINE_FEED);
dos.flush();
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static String readStream(InputStream in) {
StringBuilder sb = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String nextLine = "";
while ((nextLine = reader.readLine()) != null) {
sb.append(nextLine);
}
/* Close Stream */
if (null != in) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
private void createServiceUrl() {
if (null == params) {
return;
}
final Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
boolean isParam = false;
while (it.hasNext()) {
final Map.Entry<String, String> mapEnt = (Map.Entry<String, String>) it.next();
url.append(mapEnt.getKey());
url.append("=");
try {
url.append(URLEncoder.encode(mapEnt.getValue(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
url.append(WSConstants.AMPERSAND);
isParam = true;
}
if (isParam) {
url.deleteCharAt(url.length() - 1);
}
}
}

Categories

Resources