Servlet Upload FIle via Post - java

I am working on an application that uses HTTP requests to send data from one server to another. Everything work just fine for strings, but I don't know how to send a file (file upload from one server to another).
I've looked over some examples, but I also need to be able to send a string (a file ID) along with the file.
The request is send from a Java class in the POST Method of that class. Is is like this: Client sends upload request for a file with an ID to a storage server. That storage server then uploads that file to another storage server...so the POST request from the first server to the other is send from the POST method method of that server.
Any sample code or link in the right direction are greatly appreciated.

Found this tutorial of how you can send the multi-part data using HttpClient. Take a look

The Commons FileUpload package makes it easy to add robust, high-performance, file upload capability to your servlets and web applications.
FileUpload parses HTTP requests which conform to RFC 1867, "Form-based File Upload in HTML". That is, if an HTTP request is submitted using the POST method, and with a content type of "multipart/form-data", then FileUpload can parse that request, and make the results available in a manner easily used by the caller, mentioned here.
See this
link can help you more.
Since you said -
"I also need to be able to send a string (a file ID) along with the
file"
You will have to parse the Http request and check if the FileItem is a form field (string/text - file ID in your case)
and process it accordingly.
Here is the sample code for multipart content requests -
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
FileItemFactory factory = new DiskFileItemFactory();
FileItem item=null;
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
servletFileUpload.setSizeMax(-1);
List items =null;
if (isMultipart) {
try
{
items = servletFileUpload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
item = (FileItem) iter.next();
if (item.isFormField())
{
//get your file Id from element to match with item.getFieldName() and do whatever you want
}
else if ( !item.isFormField() ){
//save your file here
}
Hope that helps you.

Here is the solution I managed to implement and it works: http://www.dreamincode.net/forums/topic/316513-upload-file-from-one-servlet-to-another/

Related

How can I submit a text field in the POST request that uploads a blob to the Blobstore and retrieve it in the upload handler for the blob?

I have read several similar questions on StackOverflow but haven't found a solution to this problem yet.
I am uploading a blob from Android to App Engine's Blobstore through an HTTPPost to the upload URL generated by the Blobstore service. I want to be able to send some textual metadata with this request that identifies this blob. I want to retrieve this information along with the blob key in the upload handler servlet that is called after the blob is uploaded.
The problem is that the blob is uploaded using multipart encoding and App Engine does not support the Servlet v3.0 standard, so I can't use req.getPart() to get the textual part. (The blob itself is returned by the Blobstore service, so that part of the request is already parsed for us.)
How can I get around this problem by passing just one text parameter along with the file that is uploaded to the Blobstore and retrieve it in the servlet that is called after the upload of the blob?
Thanks so much for your help! Quite stuck on this one!
Here is the code that I use for HttpPost on Android:
File file = new File(filePath);
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder
.create();
entityBuilder.addBinaryBody("file", file);
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(blobUploadURL);
httpPost.setEntity(entityBuilder.build());
try {
HttpResponse response = httpClient.execute(httpPost);
statusCode = response.getStatusLine().getStatusCode();
}
UPDATE (Dec 8, '14):
I added a text-body to the entity builder before building the multipart-entity for the HttpPost request as follows:
String param="value";
entityBuilder.addTextBody("param", param);
For the servlet that handles the Blobstore's callback after the blob has uploaded, I used the method described by Google to parse an HttpPost request on App Engine in this tutorial as given below:
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String paramNames="default";
try {
ServletFileUpload upload=new ServletFileUpload();
FileItemIterator iterator=upload.getItemIterator(req);
while(iterator.hasNext()){
FileItemStream item=iterator.next();
InputStream stream=item.openStream();
if(item.isFormField()){
paramNames+=item.getFieldName() + ", ";
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
paramNames="error";
}
//save the paramNames variable in the Datastore for debugging later
saveParamNamesInDatastore(paramNames);
}
However, when I check the paramNames variable in the datastore after this operation, its value remains "default". That means no form field was found in the rewritten POST request that Blobstore passed to the upload handler servlet. Where to go from here??
There's a way to post meta data with your blob with the information that would not be represented by a blobkey:
In your upload form, include this:
method="post" enctype="multipart/form-data"
Now you can either add hidden fields:
<input type="hidden" name="myName" value="<%= myName %>"/>
Or you can add input fields:
<input type="text" name="myText" size="50" value="Enter your text"/>
In your servlet, make sure the post handler reads the meta-data
String userName = req.getParameter("myName");
Now you have the Upload form with all the information.
When you are passing the information to serve the blob, you can use
&blobkey=daffedafdfe&myName=Blah
So, you are not exactly storing the information in the blob itself, but you can include it in the upload form.
From what I can tell, the MultiPartEntityBuilder is respsonsible for mocking up an HTML "form" of enctype="multipart/form-data", and then by the time you get to the DefaultHttpClient lines, you are just sending the request from this form via POST. You should look into the documentaiton for the the entity builder. It has a function to add text fields to the "form"[1].
[1] - http://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/entity/mime/MultipartEntityBuilder.html#addTextBody(java.lang.String,%20java.lang.String)
Just in case, you might want to specify
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
after creating the object.
If that's not working, it might be advisable to post against requestbin to see exactly what you are receiving

Jersey servlet returns zip file that contains more bytes than response sent

I'm trying to implement a simple servlet that returns a zip file that is bundled inside the application (simple resource)
So I've implemented the following method in the server side:
#GET
#Path("{path}/{zipfile}")
#Produces("application/zip")
public Response getZipFile(
#PathParam("path") String pathFolder,
#PathParam("zipfile") String zipFile) IOException {
String fullPath= String.format("/WEB-INF/repository/%s/%s",
pathFolder, zipFile);
String realPath = ServletContextHolder.INSTANCE.getServletContext()
.getRealPath(fullPath);
File file = new File(realPath );
ResponseBuilder response = Response.ok((Object) file);
return response.build();
}
When I call this method from the borwser, the zip file is downloaded and its size is the same number of bytes as the original zip in the server.
However, when I call this using a simple XMLHttpRequest from my client side code:
var oXHR = new XMLHttpRequest();
var sUrl = "http://localhost:8080/path/file.zip"
oXHR.open('GET', sUrl);
oXHR.responseType = 'application/zip';
oXHR.send();
I can see in the Network tab of the Developer tools in chrome that the content size is bigger, and I'm unable to process this zip file (for instance JSzip doesn't recognize it).
It seems like somewhere between my response and the final response from org.glassfish.jersey.servlet.ServletContainer, some extra bytes are written/ some encoding is done on the file.
Can you please assist?
Best Regards,
Maxim
When you use an ajax request, the browser expects text (by default) and will try to decode it from UTF-8 (corrupting your data).
Try with oXHR.responseType = "arraybuffer"; : that way, the browser won't change the data and give you the raw content (which will be in oXHR.response).
This solution won't work in IE 6-9 : if you need to support it, check JSZip documentation : http://stuk.github.io/jszip/documentation/howto/read_zip.html
If it's not the right solution, try downloading directly the zip file (without any js code involved) to check if the issue comes from the js side or from the java side.

uploading png to server with java using POST data

Hi ive been having some trouble trying to transfer a png image to my webserver using java and php Ive tried using FTP but the software that Im scripting for blocks port 21 rendering it useless
I was directed to use form urlencoded data then use a POST request to get it
im completely lost on this topic and could just use some direction apparently file and image hosting sites use the same method to transfer files and images from the users computer to their servers.
maybe just an explanation of whats going on might help so that I can grasp what exactly im trying to do with java and php
Any help would be much appreciated!
I've also been facing the same kind of problem a short time ago.
After some researches, I found out that the HttpComponents library from Apache (http://hc.apache.org/) contains pretty much everything you'll need to build HTTP-POST request in a quite simple way.
Here is a method that will send a POST request with a file to a certain URL:
public static void upload(URL url, File file) throws IOException, URISyntaxException {
HttpClient client = new DefaultHttpClient(); //The client object which will do the upload
HttpPost httpPost = new HttpPost(url.toURI()); //The POST request to send
FileBody fileB = new FileBody(file);
MultipartEntity request = new MultipartEntity(); //The HTTP entity which will holds the different body parts, here the file
request.addPart("file", fileB);
httpPost.setEntity(request);
HttpResponse response = client.execute(httpPost); //Once the upload is complete (successful or not), the client will return a response given by the server
if(response.getStatusLine().getStatusCode()==200) { //If the code contained in this response equals 200, then the upload is successful (and ready to be processed by the php code)
System.out.println("Upload successful !");
}
}
In order to complete the upload, you must have a php code that handle that POST request,
here it is:
<?php
$directory = 'Set here the directory you want the file to be uploaded to';
$filename = basename($_FILES['file']['name']);
if(strrchr($_FILES['file']['name'], '.')=='.png') {//Check if the actual file extension is PNG, otherwise this could lead to a big security breach
if(move_uploaded_file($_FILES['file']['tmp_name'], $directory. $filename)) { //The file is transfered from its temp directory to the directory we want, and the function returns TRUE if successfull
//Do what you want, SQL insert, logs, etc
}
}
?>
The URL object given to the Java method must point to the php code, like http://mysite.com/upload.php and can be build very simply from a String. The file can also be build from a String representing its path.
I didn't take the time to test it properly, but it was build upon proper working solution, so I hope this will help you.

Download dynamic file with GWT

I have a GWT page where user enter data (start date, end date, etc.), then this data goes to the server via RPC call. On the server I want to generate Excel report with POI and let user save that file on their local machine.
This is my test code to stream file back to the client but for some reason I think it does not know how to stream file to the client when I'm using RPC:
public class ReportsServiceImpl extends RemoteServiceServlet implements ReportsService {
public String myMethod(String s) {
File f = new File("/excelTestFile.xls");
String filename = f.getName();
int length = 0;
try {
HttpServletResponse resp = getThreadLocalResponse();
ServletOutputStream op = resp.getOutputStream();
ServletContext context = getServletConfig().getServletContext();
resp.setContentType("application/octet-stream");
resp.setContentLength((int) f.length());
resp.setHeader("Content-Disposition", "attachment; filename*=\"utf-8''" + filename + "");
byte[] bbuf = new byte[1024];
DataInputStream in = new DataInputStream(new FileInputStream(f));
while ((in != null) && ((length = in.read(bbuf)) != -1)) {
op.write(bbuf, 0, length);
}
in.close();
op.flush();
op.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
return "Server says: " + filename;
}
}
I've read somewhere on internet that you can't do file stream with RPC and I have to use Servlet for that. Is there any example of how to use Servlet and how to call that servlet from ReportsServiceImpl. Do I really need to make a servlet or it is possible to stream it back with my RPC?
You have to make a regular Servlet, you cannot stream binary data from ReportsServiceImpl. Also, there is no way to call the servlet from ReportsServiceImpl - your client code has to directly invoke the servlet.
On the client side, you'd have to create a normal anchor link with the parameters passed via the query string. Something like <a href="http://myserver.com/myservlet?parm1=value1&.."</a>.
On the server side, move your code to a standard Servlet, one that does NOT inherit from RemoteServiceServlet. Read the parameters from the request object, create the excel and send it back to the client. The browser will automatically popup the file download dialog box.
You can do that just using GWT RPC and Data URIs:
In your example, make your myMethod return the file content.
On the client side, format a Data URI with the file content received.
Use Window.open to open a file save dialog passing the formatted DataURI.
Take a look at this reference, to understand the Data URI usage:
Export to csv in jQuery
It's possible to get the binary data you want back through the RPC channel in a number of ways... uuencode, for instance. However, you would still have to get the browser to handle the file as a download.
And, based on your code, it appears that you are trying to trigger the standard browser mechanism for handling the given mime-type by modifying the response in the server so the browser will recognize it as a download... open a save dialog, for instance. To do that, you need to get the browser to make the request for you and you need the servlet there to handle the request. It can be done with rest urls, but ultimately you will need a serviet to do even that.
You need, in effect, to set a browser window URL to the URL that sends back the modified response object.
So this question (about streaming) is not really compatible with the code sample. One or the other (communication protocols or server-modified response object) approach has to be adjusted.
The easiest one to adjust is the communication method.

Help with file upload in Java/J2EE

I need to upload a file using Apache fileupload with ProgressListener but alongwith that I also need to show the progressbar for the upload status.
Actual requirement is I just need to parse a local XML file parse the xml into appropriate objects and put them in Database. Do I really need to upload the file to server to get it parsed. As I am getting exception like file not found on remote server while it runs fine on my local m/c.
Any quick help would be appreciated.
Thanks in advance !!!
If you have access to the server side, I advise to debug the upload process. The exception suggests that you want to open the file on the server based on the uploaded file name. On your local machine this works, because it runs on the same file system. On the server side, the Apache FileUpload receives binary data, which needs to be extracted from the request data stream:
#Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (ServletFileUpload.isMultipartContent(request)) {
FileItemFactory factory = new DiskFileItemFactory(Integer.MAX_VALUE, null);
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request);
for (FileItem item : items) {
byte[] data = item.get();
// do something with the binary data
}
} else {
System.err.println("Not a multipart/form-data");
}
}
And also you need the form to be:
<form name='frm' method="POST" action='UploadServlet'
id="frm" enctype="multipart/form-data">
From your description it sounds like your servlet is trying to read the file from the filesystem itself, based on the filename submitted in the form. This isn't going to work if the servlet is running on a different machine to where the file is.
Make sure your servlet is getting the file contents from the fileupload API, not from the local filesystem.

Categories