Search code examples
javahttpurlconnectionmultipartform-dataxlsx

Multipart post of xlsx get corrupted via HTTPUrlConnection


I am trying to post xlsx file via HTTPUrlconnection, on receiving end I got the file but while opening it in MS Excel its saying that file is corrupted and repairing required . My code snippet for multipart post

class MultipartUtility {
        private  final Logger log = getLogger(MultipartUtility.class.getName());
        private static final String CRLF = "\r\n";
        private static final String CHARSET = "UTF-8";
        private static final int CONNECT_TIMEOUT = 1500000;
        private static final int READ_TIMEOUT = 1000000;
        private final HttpURLConnection connection;
        private final OutputStream outputStream;
        private final PrintWriter writer;
        private final String boundary;
        // for log formatting only
        private final URL url;
        private final long start;

        public MultipartUtility(final String strUrl) throws IOException {
            start = currentTimeMillis();
            URL url  = new URL(strUrl);
            this.url = url;
            boundary = "---------------------------" + currentTimeMillis();
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(CONNECT_TIMEOUT);
            connection.setReadTimeout(READ_TIMEOUT);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Accept-Charset", CHARSET);
            connection.setRequestProperty("Content-Type","multipart/form-data; boundary=" + boundary);
            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            outputStream = connection.getOutputStream();
            writer = new PrintWriter(new OutputStreamWriter(outputStream, CHARSET),true);
        }
        public void addFilePart(final String  filePath)throws IOException {
            String fieldName = "content";
            File uploadFile = new File(filePath);
            final String fileName = uploadFile.getName();
            writer.append("--").append(boundary).append(CRLF)
                    .append("Content-Disposition: form-data; name=\"")
                    .append(fieldName).append("\"; filename=\"").append(fileName)
                    .append("\"").append(CRLF).append("Content-Type: ")
                    .append(guessContentTypeFromName(fileName)).append(CRLF)
                    .append("Content-Transfer-Encoding: binary").append(CRLF)
                    .append(CRLF);

            writer.flush();
            outputStream.flush();
            try (final FileInputStream inputStream = new FileInputStream(uploadFile);) {
                final byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                outputStream.flush();
            }
            writer.append(CRLF);
        }


        public HashMap<Object, Object> finish() throws IOException {
            writer.append(CRLF).append("--").append(boundary).append("--").append(CRLF);
            writer.close();

            final int status = connection.getResponseCode();
            if (status != HTTP_OK) {
                throw new IOException(format("{0} failed with HTTP status: {1}",url, status));
            }
            try (final InputStream is = connection.getInputStream()) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                String sResponse;
                StringBuilder responseBuilder = new StringBuilder();
                while ((sResponse = reader.readLine()) != null) {
                    responseBuilder = responseBuilder.append(sResponse);
                }
                HashMap respMap = new HashMap();
                respMap.put("RESP_MSG", responseBuilder.toString());
                respMap.put("RESP_CODE", status);
                respMap.put("RESP_SIZE", responseBuilder.toString().length());
                log.log(INFO,format("{0} took {4} ms", url,(currentTimeMillis() - start)));
                log.log(INFO,"status::::::"+status);
                return respMap;
            } finally {
                connection.disconnect();
            }
        }
    }

Solution

  • I tried to execute your code and was able to successfully upload file from java program. The problem you reported is i guess due to content-type of the file. If you try to upload .xlsx (MS Excel 2007) it deforms the data and need to recover before we read uploaded file.

    If you try to upload .xls file, it uploads properly without any deform and MS excel open this file without any warning/error.

    So i would suggest to play around writer.append( "Content-Type: " + "application/x-excel")

    to find the correct content-type refer to : https://www.codeproject.com/Questions/481262/contentplustypeplusforplusxlsxplusfile

    best of luck