【问题标题】:Type error while uploading file using formData使用 formData 上传文件时输入错误
【发布时间】:2021-04-17 05:33:30
【问题描述】:

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

“未知”类型的参数不能分配给类型参数 '字符串 |斑点'。类型“{}”缺少以下属性 type 'Blob':大小、类型、arrayBuffer、切片等 2 个。

代码

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>

更多细节

console.log(file)给了

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)object

【问题讨论】:

  • 您是否尝试过投射file,或调用new Blob
  • @ZacAnger,我试过这个..const blob = new Blob([fileInput.current.files[0]]) 然后这个const formArray = Object.entries({ ...fields, file: blob });,仍然给我同样的错误
  • 我想补充的一点是我能够在开发过程中成功上传文件......它只是导致问题的打字稿错误
  • 是的,错误来自 TypeScript,所以你只需要找出正确的方法来欺骗它。 // @ts-ignore 评论会起作用,但最好弄清楚它想要什么。断言valueany 也可以:formData.append(key, value as any)const file = fileInput.current.files[0] as Blob 也许。
  • 前者有效,即不会抱怨类型错误,但后者不会...我仍然想知道console.log(file) 是否应该已经是Blob,因为__proto__File file.

标签: javascript typescript multipartform-data form-data


【解决方案1】:

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

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

resany,这使得fields 类型为any,这反过来又使formArray 类型为[string, unknown][],因此valueunknown,这会导致错误。

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

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

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

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

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

现在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>
}

对于可以通过将有问题的行更改为:

formData.append(key, value as Blob);

添加as Blob 不会改变已编译的 JS,但会使 typescript 编译器停止抱怨。

【讨论】:

    猜你喜欢
    • 2018-03-28
    • 2020-11-08
    • 2014-03-10
    • 2017-08-30
    • 2015-12-22
    • 1970-01-01
    • 2014-06-08
    • 2016-03-09
    • 2012-10-10
    相关资源
    最近更新 更多