使用 formData 上传文件时输入错误

roh*_*023 6 javascript multipartform-data form-data typescript

value我在以下部分收到的错误消息formData.append(key, value);

\n
\n

\'unknown\' 类型的参数不可分配给 \n\'string | 类型的参数 斑点\'。类型“{}”缺少\n类型“Blob”的以下属性:大小、类型、arrayBuffer、切片以及另外 2 个属性。

\n
\n

代码

\n
const uploadSubtitle = async e => {\n            e.preventDefault();\n            const file = fileInput.current.files[0];\n            const res = await Axios.get(`/api/movies/${currentMovie.movieId}/subtitles?user=${user.id}`);\n            const { url, fields } = res.data;\n            const newUrl = `https://${url.split(\'/\')[3]}.s3.amazonaws.com`;\n            const formData = new FormData();\n            const formArray = Object.entries({ ...fields, file });\n            formArray.forEach(([key, value]) => {\n                formData.append(key, value);\n            });\n           //... further code\n    };\n\n\n<form onSubmit={uploadSubtitle}>\n   <input type=\'file\' name=\'subtitle\' ref={fileInput} accept=\'.srt\' />\n   <button onClick={uploadSubtitle}>Upload</button>\n</form>\n
Run Code Online (Sandbox Code Playgroud)\n

额外细节

\n

console.log(file)给出

\n
File \n{name: "Trainspotting-English.srt", lastModified: 1587840529000, \nlastModifiedDate: Sun Apr 26 2020 00:18:49 GMT+0530 (India Standard Time), \nwebkitRelativePath: "", size: 103040, \xe2\x80\xa6}\n\nlastModified: 1587840529000 lastModifiedDate: Sun Apr 26 2020 00:18:49 GMT+0530 (India Standard Time) \n{} name: "Trainspotting-English.srt" size: 103040 \ntype: "application/x-subrip" webkitRelativePath: "" __proto__: File\n
Run Code Online (Sandbox Code Playgroud)\n

console.log(typeof file)给出\nobject

\n

Sij*_*men 5

这一切都归结为未知类型res,在此介绍:

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

resis any,它使fieldstype成为 type any,进而使formArraybe 成为 type [string, unknown][],因此valueis unknown,这会导致错误。

为了从源头上解决这个问题,我们可以在Axios.get方法上使用泛型类型,如下所示:

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

这将成为res类型{url :string, fields: {[key:string]:string}}。这导致fields类型为{[key:string]:string}

不幸的是,扩展运算符无法推断出正确的类型。代码{...fields, file}解析为 type {file: File},这并没有多大帮助。所以让我们提示一下formArray

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

现在value将是类型string|File

完整示例:

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>
}
Run Code Online (Sandbox Code Playgroud)

对于可以通过将有问题的行更改为来解决的问题来说,这是相当大量的工作:

formData.append(key, value as Blob);
Run Code Online (Sandbox Code Playgroud)

添加as Blob不会改变编译后的 JS,但会使打字稿编译器停止抱怨。