From: Arne Vajhøj on
On 03-08-2010 15:38, Dimitris wrote:
> On Aug 2, 5:06 am, Arne Vajhøj<a...(a)vajhoej.dk> wrote:
>> On 01-08-2010 21:48, PNS wrote:
>>
>>
>>
>>
>>
>>> On Jul 31, 10:26 pm, Arne Vajhøj<a...(a)vajhoej.dk> wrote:
>>>> On 31-07-2010 14:42, Public Network Services wrote:
>>
>>>>> I am playing with HttpURLConnection to upload files to a remote server
>>>>> and cannot seem to figure out a consistent way of identifying the
>>>>> Content-Type of a file to be uploaded. I assumed that "application/
>>>>> octet-stream" would be a generic type to supply, but apparently this
>>>>> is not the case.
>>
>>>>> More specifically, I can read a file into a byte array (fileBytes) and
>>>>> open an HttpConnection to a destination URL (url), but setting the
>>>>> Content-Type property does not work. The code I use is:
>>
>>>>> HttpURLConnection connection = url.openConnection();
>>>>> connection.setRequestProperty("Content-Length",
>>>>> String.valueOf(fileBytes.length));
>>>>> connection.setRequestProperty("Content-Type", "application/octet-
>>>>> stream");
>>
>>>>> If, immediately after the above, I do a
>>
>>>>> connection.getContentType()
>>
>>>>> I get a null value (or an Exception saying that the connection is
>>>>> already connected)!
>>
>>>>> Eventually, my file gets uploaded through the
>>>>> connection.getOutputStream(), by simply doing
>>
>>>>> DataOutputStream output = new
>>>>> DataOutputStream(connection.getOutputStream());
>>>>> output.write(fileContents);
>>
>>>>> but its Content-Type not being properly set causes the server to not
>>>>> recognize it (e.g., if it is an MP3 file, it does not get the
>>>>> speakerphone icon that MP3 files get in the serverś web interface,
>>>>> when uploaded via that interface, through a browser).
>>
>>>>> Obviously, this is a solved problem given the multitude of properly
>>>>> working Java-based web clients, so I 'd really aprpeciate
>>>>> someone pointing me to the correct solution.
>>
>>>>> In other words, my questions are:
>>
>>>>> (a) How can I (automatically) identify the Content-Type of a file in
>>>>> Java?
>>>>> (b) How can I properly set that Content-Type in an HttpURLConnection?
>>
>>>> application/octet-stream is fine.
>>
>>>> You need to specify method as POST.
>>
>>>> You should not use DataOutputStream just OutputStream is fine.
>>
>>>> And most important you need to know whether the receiver expects
>>>> a raw POST or a form submit with a field of type FILE.
>>
>>>> Those are not send identical!
>>> I do specify setRequestMethod("POST").
>>
>>> You are right about OutputStream, using DataOutputStream only for
>>> writing as I did makes no difference, as the latterś write() method is
>>> inherited from the former. Knowing that OutputStream is an abstract
>>> class had rather instictively turned me to another, more "concrete"
>>> stream class.
>>
>>> Also, I use application/octet and uploading works, but, as I said in
>>> my original post, the file type is wrong. This does not happen if I
>>> manually set the specific content type for a file (e.g., audio/mpeg
>>> for MP3), so it all boils down to identifying the file type (at least
>>> for the particular server application I send to).
>>
>>> One would expect that calling the standard Java
>>> connection.getFileNameMap().getContentTypeFor(filename)) would return
>>> the proper type, but it returns null, at least for teh Linux OS I am
>>> running.
>>
>>> I didn't check about the raw vs. form distinction but apparently the
>>> server is fine with raw, since it works.
>>
>>> That still leaves me looking for a "standard Java" way to identify the
>>> content type of a file. :-)
>>
>> Now I don't understand what the problem is.
>>
>> You upload file abc.xyz to the server as application/octet-stream.
>>
>> The receiving script get the file and stores the file with
>> the correct name.
>>
>> What do you need?

> As I already explained, I need a solution to a two-fold problem, a
> theoretical and a practical one.
>
> (1) Theoretical. Given a file (name and/or its contents), which is the
> "standard" Java way for defining the Content-Type to use in HTTP? This
> is such a trivial case, that there should be a quick and easy way of
> doing it. For example, as I already said, given a URLConnection
> variable, apparently one should be able to get the Content-Type by
> just calling connection.getFileNameMap().getContentTypeFor(filename)).
> In my case (Java 6 over CentOS 5.5), I get a null value, which is
> really weird, given that the filename extension is .mp3! If we were to
> just set "application/octet-stream" everywhere, then what is the need
> for all the other MIME types? Clearly, there is a need, so
> "application/octet-stream" is not the one-size-fits-all solution.

There are no 100% safe way to associate file extensions with MIME types.

It is a guessing game.

The documentation explains where Java gets its guesses from:

<quote>
Loads filename map (a mimetable) from a data file. It will first
try to load the user-specific table, defined by
"content.types.user.table" property. If that fails, it tries to load the
default built-in table at lib/content-types.properties under java home.
</quote>

> (2) Practical. The server application I send, has a web-based client.
> If I upload an mp3 file using that client, I can see the file listed
> with a nice speakerphone icon next to it, a clear sign that the server
> understands what it got. If I send the same file from my application,
> using an "audio/mpeg" Content-Type which I manually set, the same nice
> speakerphone appears in the web client. However, if I don't have an
> automated way to determine the proper Content-Type and thus use
> "application/octet-stream" instead, the file is copied to the server
> and I can download and play it just fine, but instead of the
> speakerphone I get a question mark icon in the web client. Obviously,
> the server is not fully happy with "application/octet-stream".

If the server is a normal web server serving static content
then it does nor matter.

Your upload program and the receiving script transfers filename
and the bytes of the file to the servers file system byte by byte.

Then the web server uses its own map over file extensions to
display it.

But that is browser-web server-file system. The MIME type you
specify has nothing to do with it.

If the server is running an app that has a database with filenames,
MIME types etc. then it does matter what you send.

In that case you should look in the documentation for the
server to understand what you need to send.

Arne
From: Steven Simpson on
On 31/07/10 19:42, Public Network Services wrote:
> More specifically, I can read a file into a byte array (fileBytes) and
> open an HttpConnection to a destination URL (url), but setting the
> Content-Type property does not work. The code I use is:
>
> HttpURLConnection connection = url.openConnection();
> connection.setRequestProperty("Content-Length",
> String.valueOf(fileBytes.length));
> connection.setRequestProperty("Content-Type", "application/octet-
> stream");

You've set the content type of the request.

> If, immediately after the above, I do a
>
> connection.getContentType()

getContentType() gets the content type of the response, not the
request. Do you expect it to return application/octet-stream?

> I get a null value (or an Exception saying that the connection is
> already connected)!

A null would likely indicate that the response has no content. Not sure
how you get an exception from it - are you sure it's not coming from
setRequestProperty, indicating that the request has already been
transmitted, so the call is too late?