Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
501 views
in Technique[技术] by (71.8m points)

javascript - Type error while uploading file using formData

The error message that I receive in the value part of formData.append(key, value);:

Argument of type 'unknown' is not assignable to parameter of type 'string | Blob'. Type '{}' is missing the following properties from type 'Blob': size, type, arrayBuffer, slice, and 2 more.

Code

const uploadSubtitle = async e => {
            e.preventDefault();
            const file = fileInput.current.files[0];
            const res = await Axios.get(`/api/movies/${currentMovie.movieId}/subtitles?user=${user.id}`);
            const { url, fields } = res.data;
            const newUrl = `https://${url.split('/')[3]}.s3.amazonaws.com`;
            const formData = new FormData();
            const formArray = Object.entries({ ...fields, file });
            formArray.forEach(([key, value]) => {
                formData.append(key, value);
            });
           //... further code
    };


<form onSubmit={uploadSubtitle}>
   <input type='file' name='subtitle' ref={fileInput} accept='.srt' />
   <button onClick={uploadSubtitle}>Upload</button>
</form>

Additional details

console.log(file) gives

File 
{name: "Trainspotting-English.srt", lastModified: 1587840529000, 
lastModifiedDate: Sun Apr 26 2020 00:18:49 GMT+0530 (India Standard Time), 
webkitRelativePath: "", size: 103040, …}

lastModified: 1587840529000 lastModifiedDate: Sun Apr 26 2020 00:18:49 GMT+0530 (India Standard Time) 
{} name: "Trainspotting-English.srt" size: 103040 
type: "application/x-subrip" webkitRelativePath: "" __proto__: File

console.log(typeof file) gives object


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It all comes down to the unknown type of res, introduced here:

const res = await Axios.get(`/api/movies/${currentMovie.movieId}/subtitles?user=${user.id}`);

res is any, which makes fields type any, which in turn makes formArray be of type [string, unknown][], thus value is unknown, which causes the error.

To solve this problem at the source, we can use a generic type on the Axios.get method like so:

const res = await Axios.get<{url :string, fields: {[key:string]:string}}>(`/api/movies/xxx/subtitles?user=xxx`);

This will make res be of type {url :string, fields: {[key:string]:string}}. This causes fields to be of type {[key:string]:string}.

Unfortunately the spread operator does not infer the right types. The code {...fields, file} resolves to type {file: File}, which is not really helpful. So let's hint formArray:

const formArray : [string, string|File][] = Object.entries({...fields, file});

Now value will be of type string|File.

Full example:

function App() {

    let fileInput = useRef<HTMLInputElement>(null);

    const uploadSubtitle = async (e: React.FormEvent) => {
        e.preventDefault();
        const file = fileInput.current!.files![0];
        const res = await Axios.get<{ url: string, fields: { [key: string]: string } }>(`/api/movies/xxx/subtitles?user=xxx`);
        const {url, fields} = res.data;
        const formData = new FormData();
        const formArray: [string, string | File][] = Object.entries({...fields, file});
        formArray.forEach(([key, value]) => {
            formData.append(key, value);
        });
    };
    return <form onSubmit={uploadSubtitle}>
        <input type='file' name='subtitle' ref={fileInput} accept='.srt'/>
        <button type="submit">Upload</button>
    </form>
}

This is all rather a lot of work for something that can be fixed by changing the problematic line to:

formData.append(key, value as Blob);

Adding the as Blob won't change the compiled JS but will make the typescript compiler stop complaining.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...