2

I was trying to change a file's name before uploading in my react.js application:

Here is the approach :

onInputChange = (e) =>{

    let newFileName='dp';
    if(e.target.files.length!==0){
        this.state.file=e.target.files[0];

        Object.defineProperty(this.state.file.name, 'name', {
            writable: true,
            value: newFileName
        });
        console.log(this.state.file);
    }
};

But the problem is, whenever this function gets called, I get an error saying : Object.defineProperty called on non-object

How this can be solved ?

Maifee Ul Asad
  • 3,992
  • 6
  • 38
  • 86

2 Answers2

2

You are defining a new property on a string primitive in the Object.defineProperty. The this.state.file.name is a string primitive not an object.

const onInputChange = (e) =>{
    
        let newFileName='dp';
        if(e.target.files.length!==0){
            const file = e.target.files[0];
            // file is an object
            // Since file.name is read-only, this is not the proper way to change the name
            // For a file object writable is already true
            Object.defineProperty(file , 'name', {
                value: newFileName
            });
            console.log(file.name);
   
            // Since file name is readonly, and cannot be changed after the File is created
            // This is an alternate way to set the name on a copy of the file object
            const blob = file.slice(0, file.size, file.type); 
            newFile = new File([blob], newFileName, {type: file.type});
            console.log(newFile.name);
       }
};
document.querySelector("#fileInput").addEventListener("change", onInputChange);
Upload here:
<input type="file" name="test" id="fileInput"/>

Also to update the state do not directly mutate the this.state but instead use the setState() method to update it.

Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
  • Thanks, but I have a problem. When I edit file name and `console.log` I get the file name as I want. But when I upload it to my server the name remains the old one. – Maifee Ul Asad Sep 18 '19 at 16:31
  • 1
    @MaifeeUlAsad The `name` is a readonly property , if you set the writable to `true` for file.name it still would not work. try using the alternate method I added in the answer by copying the file object itself using the File constructor. – Fullstack Guy Sep 18 '19 at 17:17
1

this.state.file.name is a string, not an object, right? Maybe you meant this.state.file? And it's not a new property. You're just changing the value. So why not this.state.file.name = newFileName?

And as Maifee points out, you may want file.filename, not file.name.

ray
  • 26,557
  • 5
  • 28
  • 27
  • I have a problem. When I edit file name and console.log I get the file name as I want. But when I upload it to my server the name remains the old one. You can see [here](https://i.stack.imgur.com/oY7yf.png) – Maifee Ul Asad Sep 18 '19 at 16:37
  • 1
    I haven't given this a lot of thought but it's possible there's a security restriction that doesn't allow you to change the file name programmatically. You might need to add a field to your form to capture the changed name. Hidden input, [`FormData.set`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/set) or [`FormData.append`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/append) – ray Sep 18 '19 at 16:58