0

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.

3 Answers3

0

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

0

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);
        }
    }
}
Community
  • 1
  • 1
11thdimension
  • 10,333
  • 4
  • 33
  • 71
  • can you please tell me the significane of this line " conn.setRequestProperty("Test", "Bonjour"); " – LoveToCode Apr 11 '16 at 09:27
  • There is none, probably the person who implemented this utility forgot to remove it after testing, I'm commenting it out in my post. – 11thdimension Apr 11 '16 at 14:55
0

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.