reading Word file from POST request in grails - http

I'm trying to write a Groovy script that will post a Word (docx) file to a REST handler on my grails application.
The request is constructed like so:
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.mime.MultipartEntity
import org.apache.http.entity.mime.content.FileBody
import org.apache.http.entity.mime.content.StringBody
import org.apache.http.impl.client.DefaultHttpClient
class RestFileUploader {
def sendFile(file, filename) {
def url = 'http://url.of.my.app';
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
MultipartEntity reqEntity = new MultipartEntity();
FileBody bin = new FileBody(file);
reqEntity.addPart("file", new FileBody((File)file, "application/msword"));
def normalizedFilename = filename.replace(" ", "")
reqEntity.addPart("fileName", new StringBody(normalizedFilename));
httppost.setEntity(reqEntity);
httppost.setHeader('X-File-Size', (String)file.size())
httppost.setHeader('X-File-Name', filename)
httppost.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=utf-8')
println "about to post..."
HttpResponse restResponse = httpclient.execute(httppost);
HttpEntity resEntity = restResponse.getEntity();
def responseXml = resEntity.content.text;
println "posted..."
println restResponse
println resEntity
println responseXml.toString()
return responseXml.toString()
}
}
On the receiving controller, I read in the needed headers from the request, and then try to access the file like so:
def inStream = request.getInputStream()
I end up writing out a corrupted Word file, and from examining the file size and the contents, it looks like my controller is writing out the entire request, rather than just the file.
I've also tried this approach:
def filePart = request.getPart('file')
def inStream = filePart.getInputStream()
In this case I end up with an empty input stream and nothing gets written out.
I feel like I'm missing something simple here. What am I doing wrong?

You will need to make two changes:
Remove the line: httppost.setHeader('Content-Type'.... File upload HTTP POST requests must have content type multipart/form-data (set automatically by HttpClient when you construct a multipart HttpPost)
Change the line: reqEntity.addPart("file", ... to: reqEntity.addPart("file", new
FileBody(file)). Or use one of the other non-deprecated FileBody constructors to specify a valid content type and charset (API link) This assumes that your file method parameter is of type java.io.File -- this isn't clear to me from your snippet.
Then, as dmahapatro suggests, you should be able to read the file with: request.getFile('file')

Related

DownLoad Shippo label through controller

After filling necessary package info, I manage to create a responsed Transaction object through goShippo API call: Transaction.create(Map, apiKey). Form the responsed Transaction object, I can get the shipping label as a Url: transaction.getObjectId().
The problem that I have is how can I enable my client to download the shipping label.
My current code is:
fileName= "https://shippo-delivery-east.s3.amazonaws.com/b1b0e6af.pdf?xxxxxx";
File file = new File(fileName);
String mineType = URLConnection.guessContentTypeFromName(file.getName());
if(mineType == null) {
System.out.println("mineType is not detectable");
mineType = "application/octet-stream";
}
response.setContentType(mineType);
response.setHeader("Content-Disposition"
, String.format("inline; filename=\"" + file.getName() +"\""));
response.setContentLength((int)file.length());
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
FileCopyUtils.copy(inputStream, response.getOutputStream());
The error that I have is that the file is not found, but when I pass the fileName on browser, I can see the shipping label.
The documentation says:
After you've successfully created a URL, you can call the URL's openStream() method to get a stream from which you can read the contents of the URL. The openStream() method returns a java.io.InputStream object, so reading from a URL is as easy as reading from an input stream.
So you need to create a URL object and from it you can get the inputStream.
It looks like this:
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.URL;
String fileName= "https://shippo-delivery-east.s3.amazonaws.com/b1b0e6af.pdf?xxxxxx";
URL urlToLabel = new URL(fileName);
InputStream inputStream = new BufferedInputStream(urlToLabel.openStream());

How to read xml response generated by HTTP POST Interface

I generate request to a certain API which is mentioned here for sending an sms http://help.voxeo.com/go/help/evolution.sms.postapi
The request generates an XML response as follow
<rsp stat="ok">
<success msg="accepted" transactionid="2e47fe224d25559a696a7bdddec1828b" messageid="cf0d21f067e5b386a2e042134687eb5c"/>
</rsp>
I want to read if rsp stat in response is ok or fail how can i do it .
These are the first two lines how can i get particular xml tag out of response stream
HttpWebResponse response = (HttpWebResponse)myReq.GetResponse();
Stream content = response.GetResponseStream();
Why not use XmlDocument to parse the XML. For example,
using(var reader = new StreamReader(content))
{
var doc = new XmlDocument();
doc.LoadXml(reader.ReadToEnd());
// you may want to compare case in-sensitive
if (doc.DocumentElement.Attributes["stat"].Value == "ok")
{
// success
}
}
(There is also Load method that would load from stream directly but I am not sure if it expects xml declaration at the beginning or not)
Yet another alternative is using XmlReader in case response could be lengthy and you wants to parse the initial bits as soon as its available.
try to read with XmlTextReader (http://msdn.microsoft.com/en-us/library/system.xml.xmltextreader%28v=vs.71%29.aspx)

Lose HttpServletRequest Parts After Reading Them

I have a servlet that receives an uploaded file. We've been having issues with a certain client's request not having a file attached or so the servlet thinks. The upload servlet is a replacement for an old one and we're using the Apache Commons FileUpload library to parse the file from the request. The old code uses the JavaZoom library. The requests client we're having issues with work perfectly fine in the old code.
In order to troubleshoot the problem, I added a bunch of logging to look at the request headers and parts to compare requests from a client that works with the one that doesn't. This is a snippet of how I'm looking at the parts:
Collection<Part> parts = request.getParts();
for(Part part : parts)
{
String partName = part.getName();
log.debug("Part=" + partName);
Collection<String> headerNames = part.getHeaderNames();
for(String headerName : headerNames)
{
String headerValue = part.getHeader(headerName);
log.debug(headerName + "=" + headerValue);
InputStream inputStream = part.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
StringBuilder builder = new StringBuilder();
try
{
for(String line=bufferedReader.readLine(); line!=null; line=bufferedReader.readLine())
{
builder.append(line);
builder.append('\n');
}
}
catch (IOException ignore)
{
// empty
}
finally
{
inputStream.reset();
}
log.debug("InputStream=" + builder.toString());
}
}
All this code works fine and I get the logging I'm expecting. However, this next bit of code doesn't act as expected:
if (isMultipart)
{
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
#SuppressWarnings("rawtypes")
List items = null;
// Parse the request
try
{
items = upload.parseRequest(request);
log.debug("items=" + items);
}
catch (FileUploadException ex)
{
log.warn("Error parsing request", ex);
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
}
the items variable is empty when it's logged. If I comment out the code for logging the request parts, this bit of code works and the items variable contains the uploaded file.
I can only assume that the act of getting/reading the parts from the request somehow removes them from it and are no longer available for further processing. Is there some way to read them for logging purposes and still retain them in the request for further processing?
The Collection<Part> parts = request.getParts(); is an Sevlet 3.0 API which is replacement for Commons Apache File Upload API.
You should be using only one of the two methods. Both have the support for processing uploaded files and parameters along with it.
Here is the Example for File Upload Using Servlet 3.0
The problem you are facing is because you are invoking this Collection<Part> parts = request.getParts(); request will consume the request input stream. And then you are using Apache Commons API to read the parts again. Because the stream is already read you are seeing no parts are available.
References for Servlet 3.0 File Upload:
Posting Data along with File
Servlet 3.0 Multipart Example
Servlet 3.0 MultipartConfig

Writing a proxy in grails

I am using Gralis 1.3.7. I am writing a controller that needs to get a PDF file from another server and return it to the client. I would like to do this in some reasonably efficient manner, such as the following:
class DocController {
def view = {
URL source = new URL("http://server.com?docid=${params.docid}");
response.contentType = 'application/pdf';
// Something like this to set the content length
response.setHeader("Content-Length", source.contentLength.toString());
response << source.openStream();
}
}
The problem I am having is figuring out how to set the content length of the response of my controller based on the information coming back from source. I wasn't able to find the documentation on the URL class as enhanced by grails.
What's the best way to proceed?
Gene
EDITED: Fixed parameter values in setHeader
UPDATED 16 mar 2012 10:49 PST
UPDATED 19 March 2012 10:45 PST
Moved follow-up to a separate question.
You can use java.net.URLConnection object that will allow you to do a bit more detailed work with the URL.
URLConnection connection = new URL(url).openConnection()
def url = new URL("http://www.aboutgroovy.com")
def connection = url.openConnection()
println connection.responseCode // ===> 200
println connection.responseMessage // ===> OK
println connection.contentLength // ===> 4216
println connection.contentType // ===> text/html
println connection.date // ===> 1191250061000
println connection.lastModified
// print headers
connection.headerFields.each{println it}
Your example should looks something like this:
class DocController {
def view = {
URL source = new URL("http://server.com?docid=${params.docid}");
URLConnection connection = source.openConnection();
response.contentType = 'application/pdf';
// Set the content length
response.setHeader("Content-Length", connection.contentLength.toString());
// Get the input stream from the connection
response.outputStream << connection.getInputStream();
}
}

Scala and html: download an image (*.jpg, etc) to Hard drive

I've got a Scala program that downloads and parses html. I got the links to the image files form the html, Now I need to transfer those images to my hard drive. I'm wondering what the best Scala method I should use.
my connection code:
import java.net._
import java.io._
import _root_.java.io.Reader
import org.xml.sax.InputSource
import scala.xml._
def parse(sUrl:String) = {
var url = new URL(sUrl)
var connect = url.openConnection
var sorce:InputSource = new InputSource
var neo = new TagSoupFactoryAdapter //load sUrl
var input = connect.getInputStream
sorce.setByteStream(input)
xml = neo.loadXML(sorce)
input.close
}
My blog
Then you may want to take a look at java2s. Although the solution is in plain Java but you can still modify to Scala syntax to "just use it"
An alternative option is to use the system commands which is much cleaner
import sys.process._
import java.net.URL
import java.io.File
object Downloader {
def start(location: String) : Unit = {
val url = new URL(location)
var path = url match {
case UrlyBurd(protocol, host, port, path) => (if (path == "") "/" else path)
}
path = path.substring(path.lastIndexOf("/") + 1)
url #> new File(path) !!
}
}
object UrlyBurd {
def unapply(in: java.net.URL) = Some((
in.getProtocol,
in.getHost,
in.getPort,
in.getPath
))
}
One way to achieve that is: collect the URLs of the images and ask for them to the server (open a new connection with the image url and store the bytestream in the hard drive)

Resources