4

I have the following.

<form method="post" action="/send" enctype="multipart/form-data">
    <input type="file" name="filename" id="AttachFile">
</form>

I want to change the name of the file the user uploads.

If the user selects "Document.docx" I want to change it to "Bank - Document.docx".

I still want to read the file the user selected, not some other file, just use a different name for it when sending to the server.

I'm working within bounds of an application which doesn't allow control of the server side, so ideally I need to do this on the client. Furthermore I need this to work within the confines of a form.

I have tried variations of the following without success:

document.getElementById("AttachFile").name = "test.txt"
document.getElementById("AttachFile").files = "test.txt"
document.getElementById("AttachFile").value ="test.txt"
James Wood
  • 17,286
  • 4
  • 46
  • 89

3 Answers3

6

You can do it through the File API. We can also use the Blob API to be compatible with Microsoft edge.

var file = document.getElementById("AttachFile").files[0];
var newFile = new File([file], "Bank - Document.docx", {
  type: file.type,
});

Here's a complete example — see comments:

HTML:

<input type="file" id="AttachFile">
<input type="button" id="BtnSend" value="Send">

JavaScript:

document.getElementById("BtnSend").addEventListener("click", function() {
    // Get the file the user picked
    var files = document.getElementById("AttachFile").files;
    if (!files.length) {
        return;
    }
    var file = files[0];
    // Create a new one with the data but a new name
    var newFile = new File([file], "Bank - Document.docx", {
      type: file.type,
    });
    // Build the FormData to send
    var data = new FormData();
    data.set("AttachFile", newFile);
    // Send it
    fetch("/some/url", {
        method: "POST",
        body: data
    })
    .then(response => {
        if (!response.ok) {
            throw new Error("HTTP error " + response.status);
        }
        return response.text(); // or response.json() or whatever
    })
    .then(response => {
        // Do something with the response
    })
    .catch(error => {
        // Do something with the error
    });
});
man tou
  • 129
  • 5
  • ...and then send that file via [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch) using [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData). Excellent. I **knew** something was bothering me. – T.J. Crowder Aug 10 '18 at 09:38
  • Does Edge support the fetch API ? – anjanesh Aug 10 '18 at 10:04
  • Do you think this would work within the confines of a `form`? I've updated my question - sorry should have put it in before. – James Wood Aug 10 '18 at 11:42
  • @anjanesh - [Yes, since v14](https://caniuse.com/#search=fetch) (and `FormData` since v12). To support Edge v12 and v13 you could use `XMLHttpRequest`. – T.J. Crowder Aug 10 '18 at 11:50
2

You can't rename the file using a standard form submission. The name of the file being uploaded is read-only. To do this, you'd have to do it server-side. (The designers of file uploads seem to have either not considered this rename-on-upload use case or not felt it needed to be addressed by the API.)

However, you can prevent the default form submission and instead submit it programmatically via ajax, which does allow you to rename the file; see man tou's answer.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

If you cannot work on the server side then you have to either rename the file BEFORE upload or AFTER download. How you present the name for the user is you to decide.

Simon Jensen
  • 287
  • 5
  • 24