Google App Engine Java HTTP Post Image from API Method to Servlet - java

I hope someone can help me out.
I want to send a url as a string to the client endpoint function and then I want the endpoint function to download the image and send it then via a HTTP Post request to my servlet (also running on GAE).
The problem is - there is no image posted at all.
It's strange because if I use the exact same code (the HttpPost class) on an android client, it works fine - the image gets posted to the servlet and the servlet stores the image into the datastore / blobstore.
Isn't it possible to send a HTTP Post request from a client endpoint function to a servlet?
Solved, see answer below!
Android:
BackendApi.anyMethod("url-to-any-image").execute();
Client Endpoint Function:
#ApiMethod(path = "anyMethod")
public void anyMethod(#Named("url") String url) {
// --------------------------------------------------
// No input validation here - just a proof of concept
// --------------------------------------------------
try {
// Download image
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
Resources.asByteSource(new URL(url)).copyTo(buffer);
// Upload image
HttpPost httpPost = new HttpPost();
httpPost.setTarget(new URL(BlobstoreServiceFactory.getBlobstoreService().createUploadUrl("/upload")));
httpPost.add("image", buffer.toByteArray());
httpPost.send();
} catch (IOException e) {
LOG.log(Level.WARNING, e.getMessage(), e);
}
}
HttpPost Class:
public class HttpPost {
private final static String CRLF = "\r\n";
private String boundary;
private URL url;
private ByteArrayOutputStream buffer;
public HttpPost() {
// Generate random boundary
// Boundary length: max. 70 characters (not counting the two leading hyphens)
byte[] random = new byte[40];
new Random().nextBytes(random);
boundary = Base64.encodeBase64String(random);
// Init buffer
buffer = new ByteArrayOutputStream();
}
public void setTarget(URL url) {
this.url = url;
}
public void add(String key, String value) throws IOException {
addToBuffer("--" + boundary + CRLF);
addToBuffer("Content-Disposition: form-data; name=\"" + key + "\"" + CRLF);
addToBuffer("Content-Type: text/plain; charset=UTF-8" + CRLF + CRLF);
addToBuffer(value + CRLF);
}
public void add(String key, byte[] fileBytes) throws IOException {
addToBuffer("--" + boundary + CRLF);
addToBuffer("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + key + "\"" + CRLF);
addToBuffer("Content-Type: application/octet-stream" + CRLF);
addToBuffer("Content-Transfer-Encoding: binary" + CRLF + CRLF);
addToBuffer(fileBytes);
addToBuffer(CRLF);
}
public void send() throws IOException {
// Add boundary end
addToBuffer("--" + boundary + "--" + CRLF);
// Open url connection
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
connection.setRequestProperty("User-Agent", "Google App Engine");
// Open data output stream
DataOutputStream request = new DataOutputStream(connection.getOutputStream());
request.write(buffer.toByteArray());
request.flush();
request.close();
// Close connection
connection.disconnect();
}
private void addToBuffer(String string) throws IOException {
buffer.write(string.getBytes());
}
private void addToBuffer(byte[] bytes) throws IOException {
buffer.write(bytes);
}
}
Http Servlet:
public class Upload extends HttpServlet {
private static final Logger LOG = Logger.getLogger(Upload.class.getName());
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request);
List<BlobKey> blobKeys = blobs.get("image");
if (blobKeys == null) {
LOG.warning("No blobkeys found");
return;
}
// Get blob key
BlobKey blobKey = blobKeys.get(0);
if (blobKey == null) {
LOG.warning("No blobkey found");
return;
}
// Create new image object
Image image = new Image();
image.setBlobKey(blobKey);
image.setTimestamp(new Date());
// Save image to datastore
OfyService.ofy().save().entity(image).now();
LOG.log(Level.INFO, "Image upload successful");
}
}

Accordingly to the Google App Engine Docs you are not allowed to fetch your own URL:
To prevent an app from causing an endless recursion of requests, a request handler is not allowed to fetch its own URL. It is still possible to cause an endless recursion with other means, so exercise caution if your app can be made to fetch requests for URLs supplied by the user.
That means the only way of doing this is to download the image on the Android client and then post it to the HttpServlet.
Android:
try {
// Download image to the Android client
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
Resources.asByteSource(new URL(url)).copyTo(buffer);
// Upload image to HttpServlet
HttpPost httpPost = new HttpPost();
httpPost.setTarget(new URL("http-servlet-upload-url"));
httpPost.add("image", buffer.toByteArray());
httpPost.send();
} catch (IOException e) {
Logcat.error(e.getMessage());
}

Related

How to construct correct MultipartEntity to send a multipart/related request in java?

I want to send to OCR image from local computer, not some remote url with image there (this case working great). But the problem is, I don't know how construct correctly payload of multipart entity. My payload should be looking as it described below.
This's what described in documentation of API. Decode the image data given directly in the multipart/related data. The order is important, and the first part should be the JSON, which tells it which OCR engine to use. The schema for thi JSON is documented in the /ocr endpoint. The img_url parameter of the JSON will be ignored in this case.
The image attachment should be the second part, and it should work with any image content type (eg, image/png, image/jpg, etc).
Request (multipart/related; boundary=---BOUNDARY)
-----BOUNDARY
Content-Type: application/json
{"engine":"tesseract"}
-----BOUNDARY
-----BOUNDARY
Content-Disposition: attachment;
Content-Type: image/png
filename="attachment.txt".
PNGDATA.........
-----BOUNDARY
Here's what I've tried. To perform multipart/related request I am using org.apache.httpcomponents
CloseableHttpClient httpClient = HttpClients.createDefault();
MultipartEntityBuilder multipartEntityBuilder =
MultipartEntityBuilder.create().setBoundary(BOUNDARY).setContentType(ContentType.APPLICATION_JSON).addTextBody("engine", "tesseract")
.setBoundary(BOUNDARY).setBoundary(BOUNDARY);
multipartEntityBuilder.addBinaryBody("file_upload", new File(fileTextPath), ContentType.create(CONTENT_TYPE), fileTextPath).setBoundary(BOUNDARY);
HttpEntity entity = multipartEntityBuilder.build();
HttpPost httpPost = new HttpPost(URL);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_MULTIPART+";boundary="+BOUNDARY);
httpPost.setEntity(entity);
I resolved this problem a few weeks ago and for convenience created a lightweight java web application for both cases (remote and file upload).
You can find the particular answer for the question above here. The source code for a multipart request is shown below:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class MultipartUtility {
private static final Logger logger = LoggerFactory.getLogger(MultipartUtility.class);
private final String boundary = UUID.randomUUID().toString();
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer;
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
*
* #param requestURL
* #param charset
* #throws IOException
*/
public MultipartUtility(String requestURL, String charset) {
this.charset = charset;
try {
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/related; boundary=\"" + boundary + "\"");
httpConn.setRequestProperty("Accept-Encoding", "gzip");
outputStream = httpConn.getOutputStream();
//outputStream = System.out;
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true);
} catch (IOException ex) {
logger.error("Error during creation of MultiPart: ", ex);
}
}
/**
* Adds a form field to the request
*/
public void addFormField(String jsonBody) {
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Type: application/json;").append(LINE_FEED);
writer.append(LINE_FEED);
writer.append(jsonBody).append(LINE_FEED);
writer.flush();
}
/**
* Adds a upload file section to the request
*
* #param uploadFile a File to be uploaded
* #throws IOException
*/
public void addFilePart(File uploadFile) {
String fileName = uploadFile.getName();
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Disposition: attachment;");
writer.append(" filename=\"" + fileName + "\".").append(LINE_FEED);
writer.append("Content-Type: image/*").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
try {
FileInputStream inputStream = new FileInputStream(uploadFile);
//byte[] buffer = new byte[(int) uploadFile.length()];
byte[] buffer = Files.readAllBytes(Paths.get(uploadFile.getPath()));
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
} catch (IOException ex) {
logger.error("File transformation to bytes went wrong: {}", ex);
}
writer.append(LINE_FEED);
writer.flush();
}
/**
* 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) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
}
/**
* Completes the request and receives response from the server.
*
* #return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* #throws IOException
*/
public String finish() {
String response = "";
int status = 0;
writer.flush();
writer.append("--").append(boundary).append("--").append(LINE_FEED);
writer.println();
writer.close();
try {
// checks server's status code first
status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
response += line;
}
reader.close();
httpConn.disconnect();
} else {
logger.error("OCR API returned error stream: {}", printErrorStream());
throw new IOException("Server returned non-OK status: " + status + " : " + httpConn.getResponseMessage());
//logger.error("Server returned non-OK status: " + status + " : " + httpConn.getResponseMessage());
}
} catch(IOException ex) {
logger.error("Response message in Multipart finish has been received with problems: ", ex);
}
return response;
}
private String printErrorStream() throws IOException {
//System.out.print("DEBUG System out ocr API error stream: ");
InputStream errorStream = httpConn.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String errLine = "", tempLine;
while ((tempLine = reader.readLine()) != null) {
errLine += tempLine;
}
return errLine;
}
private void getRequestHeaders(HttpURLConnection httpURLConnection) {
for (Map.Entry<String, List<String>> entries : httpURLConnection.getRequestProperties().entrySet()) {
String values = "";
for (String value : entries.getValue()) {
values += value + ",";
}
System.out.println("Request" + " " + entries.getKey() + " - " + values );
}
}
}

How to post ByteArrayOutputStream via http

I am currently reading a file from then writing it to an HTTP connection which saves the file locally to disk - it's working fine.
However, because of the environment I'm working within I cannot read files from disk, rather they are pulled from a database and stored in a ByteArrayOutputStream in my java code.
So instead of starting by reading a file from disk, I need to use a ByteOutputArrayStream and write that to an http connection instead.
I need an efficient method to do this - If I can modify my current code (bloew) that's fine - I'm willing to scrap it all if necessary...
// This is the primary call from jsp
public String postServer(String[] args)throws Exception{
System.out.println("******* HTTPTestJPO inside postServer");
String requestURL = "http://MyServer:8080/TransferTest/UploadServlet";
String charset = "UTF-8";
String sTest=args[0];
String sResponse="";
System.out.println("******* HTTPTestJPO incoming file string sTest:"+sTest);
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
StringTokenizer inFiles=new StringTokenizer(sTest,",");
while(inFiles.hasMoreTokens()){
String tmpFileName=inFiles.nextToken();
System.out.println("******* tokenized tmpFileName:"+tmpFileName);
File uploadFile1 = new File(tmpFileName);
try {
multipart.addFilePart("fileUpload", uploadFile1);
} catch (IOException ex) {
System.err.println("******* HTTPTestJPO EXCEPTION: "+ex);
}
}
sResponse = multipart.handleFinish();
System.out.println("******* HTTPTestJPO SERVER REPLIED:"+sResponse);
return sResponse;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Multipart utility
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* This utility class provides an abstraction layer for sending multipart HTTP
* POST requests to a web server.
* #author www.codejava.net
*
*/
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;
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
* #param requestURL
* #param charset
* #throws IOException
*/
public MultipartUtility(String requestURL, String charset)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", "CodeJava Agent");
//httpConn.setRequestProperty("Test", "Bonjour");
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),true);
}
/**
* 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();
// HOW CAN I MODIFY THIS TO SEND AN EXISTING BYTEARRAYOUTPUTSTREAM INSTEAD OF A DISK FILE??
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
}
/**
* Completes the request and receives response from the server.
* #return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* #throws IOException
*/
private String handleFinish() throws IOException {
String sResponse = "";
//close out the multipart send
writer.append(LINE_FEED).flush();
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.close();
// checks server's status code first
int status = httpConn.getResponseCode();
sResponse=Integer.toString(status);
System.out.println("******* HTTPTestJPO http response code:"+status);
// if (status == HttpURLConnection.HTTP_OK) {
// BufferedReader reader = new BufferedReader(new InputStreamReader(
// httpConn.getInputStream()));
// String line = reader.readLine();
// while ((line = reader.readLine()) != null) {
// sResponse+=line;
// }
// reader.close();
httpConn.disconnect();
// } else {
// throw new IOException("Server returned non-OK status: " + status);
// }
return sResponse;
}
}
}
The contents of a ByteArrayOutputStream can be written to another OutputStream using the writeTo method, like this:
byteArrayOutputStream.writeTo(outputStream);
Another option would be to create a new InputStream:
InputStream inputStream = new ByteArrayInputStream(
byteArrayOutputStream.toByteArray());
but calling toByteArray makes a copy of the byte array, so is more expensive.

FileNotFoundException for config.properties in aws lambda test console

I have an AWS lambda sample, created using AWS Toolkit for eclipse. I added a config.properties file in the project from eclipse. I am also then uploading using right click project->Amazon Web Services -> Upload
But when I test on aws console, it gives me filenotfound for config.properties.
Please help!
Here is my project structure: I get error at line 33 telling that config.properties file not found.
here is my lambda function:
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class LambdaFunctionHandler implements RequestHandler<String, WebConnectResponse> {
#Override
public void handleRequest(String input, Context context) {
context.getLogger().log("Input: " + input);
try {
new PreviewService().GetPreview(input);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void GetPreview(String downloadUrl) throws Exception{
input = new FileInputStream("config.properties"); //ERROR HERE: FileNotFoundException by aws lambda when testing on aws lambda console.
props.load(input);
//Download File
downloadFileFromUrl(new URL(downloadUrl));
return null;
}
public void downloadFileFromUrl(URL downloadUrl)throws Exception{
FileUtils.copyURLToFile(downloadUrl, new File("<filepath>"));
uploadFileToServer("<filepath>");
}
public void uploadFileToServer(String filePath) throws Exception
{
String fileExternalRefId = "id";
String param = getProperty("param");
URL uploadUrl = new URL(getProperty("uploadurl"));
File contents = new File("<filepath>");
String boundary = Long.toHexString(System.currentTimeMillis());
String CRLF = "\r\n"; //Line Separator required by multipart/form-data
URLConnection connection = uploadUrl.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
connection.addRequestProperty("file_name", contents.getName());
connection.addRequestProperty("id", fileId);
try(
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"), true);
) {
//Send headers/params
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append("Content-Type: application/xml; charset=UTF-8").append(CRLF);
writer.append(CRLF).append(param).append(CRLF).flush();
//Send contents
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"file-content\"; filename=\"" + contents.getName() + "\"").append(CRLF);
writer.append("Content-Type: application/xml; charset=UTF-8").append(CRLF);
writer.append(CRLF).flush();
Files.copy(contents.toPath(), output);
//IOUtils.copy(in, output);
output.flush();
writer.append(CRLF).flush();//It indicates end of boundary
writer.append("--" + boundary + "--").append(CRLF).flush();
}
int responseCode = ((HttpURLConnection) connection).getResponseCode();
if(responseCode == 200)
{
System.out.println(responseCode);
String viewUrl = props.getProperty("url")
System.out.println(viewUrl);
}
}
public String getProperty(String key)
{
return props.getProperty(key);
}
}
Here is my config.properties that looks like
key1=value1
key2=value2
I have little experience with AWS, but when you work with java Files or FileInputStreams must use the file path and you are using just the file name.
I think your code should be:
input = new FileInputStream("/[appDeployPath]/config.properties");
Maybe a better approach is to use:
getClass().getClassLoader().getResource("config.properties")
I also had config file in my project, and this is how I read the content of this file, I have answered the question here -
https://stackoverflow.com/a/42757653/5892553

I have an incoming HttpServletRequest that contains a request part that I need to pass into a new httpUrlConnection

Let me see if I can explain this. The front-end provides me with a spreadsheet that I need to pass to my central server via an api call to do the processing. I use the following code to pull out the spreadsheet and create my work book,
Part spreadsheet = request.getPart(SPREADSHEET);
Workbook workbook = WorkbookFactory.create(spreadsheet.getInputStream());
Where 'request' is an incoming HttpServletRequest object. I know that it works and I can manipulate the spreadsheet, but I need to pass it along to my other server to do the processing and I can't figure out how to do that. Here is what I have so far.
#Path("/uploadSpreadsheet")
#POST
public String uploadSpreadsheet(#Context final HttpServletRequest request,#Context final HttpHeaders httpHeaders) throws IOException, ServletException, InvalidFormatException, JSONException {
return uploadUtil(request, "rest/memberService/uploadSpreadsheet");
}
Here is the util that I can't get right.
private String uploadUtil(HttpServletRequest request, String serviceUrl) throws MalformedURLException, ProtocolException, IOException, ServletException {
String baseUrl = "http://localhost:8084/centralservices/";
String urlString = baseUrl.concat(serviceUrl);
URL url = new URL(urlString);
String boundary = "===" + System.currentTimeMillis() + "===";
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setRequestMethod("POST");
httpCon.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
httpCon.setRequestProperty("Key", "SOMEKEYHERE");
httpCon.setRequestProperty("clientAddress", request.getRemoteAddr());
//I know this is wrong but I'm not sure what goes here:
httpCon.setRequestProperty("file", request.getPart(SPREADSHEET));
int responseCode;
StringBuilder resp = new StringBuilder();
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(httpCon.getInputStream(), "UTF-8"));
String inputLine;
while ((inputLine = in.readLine()) != null) {
resp.append(inputLine);
}
} finally {
if (in != null) {
in.close();
}
httpCon.disconnect();
}
return resp.toString();
}
Hopefully that makes sense. I mean all I really need to do is transfer the request identically(with all the formparts and everything) to a different url. Once it gets there I have no issue processing it. Let me know if I am unclear on something. I'm pretty new to this stuff. We already have a rest utility that I've always used for everything else, but it doesn't work for this scenario so I need to create a new one.
If you are using the Servlet-Api 3.0, then the below approach gives you on how to read the stream and write back the stream to the subsequent URL.
http://balusc.omnifaces.org/2009/12/uploading-files-in-servlet-30.html
From your code above , once you get the Part , convert the obtained file/workbook to bytebuffer and then write it to Output stream.
connection.getOutputStream().write(filebuff);
Because adding to request property will not help in this case.
Thanks
Maruthi
I was too unfamiliar with some of the options presented so I just converted the spreadsheet into a json string and sent that over with my existing rest utility.
I think there's a lot of stuff missing in the multipart request. See this link
Sending files using POST with HttpURLConnection.
Also it's probably better to use some API to do this for you, probably easiest would be apache httpclient
See the example usage in this SO post
If you do need to use URLConnection for this then you can use this multipart utility from codejava.net
I'm posting the code from there here for backup in case original link goes down.
MultipartUtility
package net.codejava.networking;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/**
* This utility class provides an abstraction layer for sending multipart HTTP
* POST requests to a web server.
* #author www.codejava.net
*
*/
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;
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
* #param requestURL
* #param charset
* #throws IOException
*/
public MultipartUtility(String requestURL, String charset)
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", "CodeJava Agent");
/*Following line has no significance for the task this utility performs*/
/*httpConn.setRequestProperty("Test", "Bonjour");*/
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
}
/**
* 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();
}
/**
* 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 ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
}
/**
* 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) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
}
/**
* Completes the request and receives response from the server.
* #return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* #throws IOException
*/
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();
// checks server's status code first
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
httpConn.disconnect();
} else {
throw new IOException("Server returned non-OK status: " + status);
}
return response;
}
}
Test Program
package net.codejava.networking;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* This program demonstrates a usage of the MultipartUtility class.
* #author www.codejava.net
*
*/
public class MultipartFileUploader {
public static void main(String[] args) {
String charset = "UTF-8";
File uploadFile1 = new File("e:/Test/PIC1.JPG");
File uploadFile2 = new File("e:/Test/PIC2.JPG");
String requestURL = "http://localhost:8080/FileUploadSpringMVC/uploadFile.do";
try {
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addHeaderField("User-Agent", "CodeJava");
multipart.addHeaderField("Test-Header", "Header-Value");
multipart.addFormField("description", "Cool Pictures");
multipart.addFormField("keywords", "Java,upload,Spring");
multipart.addFilePart("fileUpload", uploadFile1);
multipart.addFilePart("fileUpload", uploadFile2);
List<String> response = multipart.finish();
System.out.println("SERVER REPLIED:");
for (String line : response) {
System.out.println(line);
}
} catch (IOException ex) {
System.err.println(ex);
}
}
}

How to upload large files by multipart request in Java?

I am using this tutorial to upload large files but it is unable to upload even 300KB of file. Also it does not upload anything other than *.txt or *.log files. Need pointers which can help me upload large files irrespective of filetypes.
Sharing modified code
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
public MultipartUtility(String requestURL, String charset)
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", "CodeJava Agent")
httpConn.setRequestProperty("Test", "Bonjour")
outputStream = httpConn.getOutputStream()
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, 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 ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead)
}
outputStream.flush()
inputStream.close()
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()
// checks server's status code first
int status = httpConn.getResponseCode() //<- Exception coming in this line java.io.IOException: Error writing to server
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpConn.getInputStream()))
String line = null
while ((line = reader.readLine()) != null) {
response.add(line)
}
reader.close()
httpConn.disconnect()
} else {
throw new IOException("Server returned non-OK status: " + status)
}
return response
}
static main(args) {
String charset = "UTF-8";
File uploadFile1 = new File("C:\\1392943434245.xml");
String requestURL = "http://localhost:10060/testme";
try {
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addFilePart("fileUpload", uploadFile1);
List<String> response = multipart.finish();
println("SERVER REPLIED:");
for (String line : response) {
System.out.println(line);
}
} catch (IOException ex) {
System.err.println(ex);
}
}
}
Have you checked that your HTTP server does not impose a size limit on requests ?
Is there enough memory and disk size ?
Maybe the cause is not in your code.
Try this code, you can be able to upload any file type
public class TryFile {
public static void main(String[] ar) throws HttpException, IOException, URISyntaxException {
// TODO Auto-generated method stub
TryFile t=new TryFile();
t.method();
}
public void method() throws HttpException, IOException, URISyntaxException
{
String url="<your url>";
String fileName="<your file name>";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
FileBody fileContent= new FileBody(new File(fileName));
StringBody comment = new StringBody("Filename: " + fileName);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("file", fileContent);
httppost.setEntity(reqEntity);
System.out.println("post length"+reqEntity.getContentLength());
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
System.out.println("end"+resEntity.getContentLength());
}
}
This is a working code for file upload:
<jsp:useBean id="upBean" scope="session" class="javazoom.upload.UploadBean" >
<jsp:setProperty name="upBean" property="filesizelimit" value="<%= 1024 * 1024%>" />
</jsp:useBean>
try this,
try {
if (MultipartFormDataRequest.isMultipartFormData(request)) {
MultipartFormDataRequest mrequest = new MultipartFormDataRequest(request);
Hashtable files = mrequest.getFiles();
byte data[] = null;
if ((files != null) && (!files.isEmpty())) {
fileObj = (UploadFile) files.get("fileUpload");
m_imagename = fileObj.getFileName().trim();
//File type validator
if (!Utility.isValiedFileName1(m_imagename)) {
ERROR = "Invalid File Type";
response.sendRedirect("XXX.jsp");//response page
return;
}
//file uploader method call
if ((fileObj != null) && (fileObj.getFileName() != null)) {
data = fileObj.getData();
//Java method for uploading
result = imageUpload.copyImage(data);//depCode
}
}
}
} catch (Exception e) {
SystemMessage.getInstance().writeMessage(" ERROR : " + e);
}
This is part related to HTTP.
Refer
here
We can upload any number of files of any sizes using plupload.

Categories