GNG
GNG

Reputation: 1531

Posting multipart form with inputstream rather than a file in Java

I would like to post CSV formatted data to an external URL. The URL requires a multipart form containing a string and a file. It seems to me that this requires saving a file to disk before I can call the URL. Is it possible to use this URL (It is the US Census Bureau's geocoding service) without saving a file to disk? For example, can I use a ByteArrayInputStream that only lives temporarily in memory? Below is my initial code that involves saving a file to disk.

        String benchmark = "9";
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost uploadFile = new HttpPost("https://geocoding.geo.census.gov/geocoder/locations/addressbatch");
        MultipartEntityBuilder builder2 = MultipartEntityBuilder.create();
        builder2.addTextBody("benchmark", benchmark, ContentType.TEXT_PLAIN);
        File f = new File("UscbGeocodingInput.csv");
        FileInputStream is = new FileInputStream(f);

        builder2.addBinaryBody(
                "addressFile",
                is,
                ContentType.APPLICATION_OCTET_STREAM,
                f.getName());

        HttpEntity multipart = builder2.build();
        uploadFile.setEntity(multipart);
        CloseableHttpResponse response = httpClient.execute(uploadFile);

I don't want to save a file to disk because it only needs to exist temporarily until we call the external URL. I tried to use a byte array input stream in instead of a FileInputStream, but the request then fails this way with a 400 error.

Upvotes: 1

Views: 3962

Answers (2)

GNG
GNG

Reputation: 1531

This worked... Turns out the US Census Bureau's geocoding API looks for a filename ending in '.csv'. Even though I'm passing in a byte array rather than a file, you still need to give a name to that input stream.

        String benchmark = "9";
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost uploadFile = new HttpPost("https://geocoding.geo.census.gov/geocoder/locations/addressbatch");
        MultipartEntityBuilder builder2 = MultipartEntityBuilder.create();
        builder2.addTextBody("benchmark", benchmark, ContentType.TEXT_PLAIN);
        byte[] addressFileAsBytes = baos.toByteArray();
//      AnalyzeInputStream(is);

        builder2.addBinaryBody(
                "addressFile",
                addressFileAsBytes,
                ContentType.APPLICATION_OCTET_STREAM,
                "anyStringThatEndsInDotCSV.csv");
        HttpEntity multipart = builder2.build();
        uploadFile.setEntity(multipart);
        CloseableHttpResponse response = httpClient.execute(uploadFile);
        HttpEntity responseEntity = response.getEntity();

Upvotes: 1

Andreas
Andreas

Reputation: 159096

Can I use a ByteArrayInputStream?

Yes, but why would you do that when there is an overload that takes the byte[] directly?

addBinaryBody(String name, byte[] b, ContentType contentType, String filename)

Upvotes: 0

Related Questions