How can I upload a file using `curl` instead of the form?

1

1

I have a client who's customer uses a third party clearinghouse to receive invoices. We can do this manually by exporting our data to XML, going to a particular website, and uploading the file. The relevant HTML form looks like this:

<form border=0
      method="POST"
      action="/server?request=send"
      enctype="multipart/form-data"
      id="uploadform"
      name="uploadform"
      onsubmit="return checkUpload()">
  <H2>Upload</H2>
  <p>Server directory:<br>
  <input type="text"
         id="directory"
         name="directory"
         value="./"
         size="30"></p>
  <p>Local file to be uploaded:<br>
  <input type="file"
         id="file"
         name="file"
         size="40"></p>
  <p><input type="submit" value="Send"></p>
</form>

Manual submission using their web interface works fine. I'm trying to write a quick tool that submits the form for us using curl. I've tried many different attempts, but so far, each one, although I get a "File successfully uploaded" HTML response, the file they get is empty.

We originally started trying to use curl because it was how the clearinghouse company suggested we do so. The example they gave was this:

curl -i -k -H "Content-Type:application/octet-stream" \
  -d @test.txt -u username:password \
  https://example.com/server?request=send?filename=test.txt?directory=DX001

When that didn't work, I began looking at the code in the form above, and tried the following (while in the same directory as the XML file):

curl -F "request=send" -F "directory=DX001" -F "file=33823.xml" \
  -u username:password -F "enctype=\"multipart/form-data\"" \
  -F "id=\"uploadform\"" https://example.com/server

When that didn't work, I thought I'd try the absolute path even though I was in the same directory:

curl -F "request=send" -F "directory=DX001" -F "file=/Users/chuck/Desktop/33823.xml" \
  -u username:password -F "enctype=\"multipart/form-data\"" \
  -F "id=\"uploadform\"" https://example.com/server

Every single one of these only uploads an empty file (with the given file's name).

As you can probably tell from the full path, I'm doing this from macOS, in case that's relevant.

Note, the onsubmit action within the form simply ensures that neither the directory nor the file inputs are empty.

Chuck

Posted 2018-07-10T21:02:41.350

Reputation: 145

1

It's probably best to look in the development tools before manually submitting the form as suggested in this answer

– davidmneedham – 2018-07-10T21:38:26.000

I completely agree with @davidmneedham. Send good HTTP header fields. Also, their web interface uses maybe an unique session cookie (token). – Jerry – 2018-07-11T00:52:03.397

Answers

2

Every single one of these only uploads an empty file (with the given file's name).

Curl doesn't know which fields are regular text and which are file upload; it assumes the former unless you specifically tell it to do the latter. To attach a whole file, you need the @ prefix:

-F "file=@/Users/chuck/Desktop/33823.xml"

You can give the server a different filename like this:

-F "file=@\"/Users/chuck/Desktop/temp.xml\";filename=\"33823.xml\""

The correct full command should be:

curl -u username:password \
     -F "directory=DX001" \
     -F "file=@/Users/chuck/Desktop/33823.xml" \
     https://example.com/server?request=send

Note how request=send is not part of the form data; it was part of the URL before, it is still part of the URL now. Finally, although your examples all include -u for authentication, remember that it only works for the HTTP 'Basic' mechanism, not for form/cookie-based login pages.

user1686

Posted 2018-07-10T21:02:41.350

Reputation: 283 655