Nodejs Axios将文件发送到Symfony API

daupos2t  于 12个月前  发布在  iOS
关注(0)|答案(1)|浏览(140)

我正在使用一个外部API,它是用Symfony(5.4.31)编写的。
我自己的代码是用NestJS编写的,我正在尝试使用Axios将本地文件发送到Symfony API。
我的问题是,该文件在API上是空的。
这是一个经典的测试:

import * as FormData from 'form-data';

const stream = fs.createReadStream(filePath);
const form = new FormData();
form.append('file', stream, 'file.pdf');
axios({
    method: 'post',
    url: url,
    data: form,
    headers: {
        "Authorization": "Bearer "+token, 
        ...form.getHeaders()
        }
    })
    .then(function (response) {
        console.log(response.data);
    })
    .catch(function (response) {
        console.log(response);
    });

字符串
我知道API正在检查文件是否存在:

) : DocumentFileApiDto {        $uploadedFile = $request->files->get('file');        if($uploadedFile === null) {            throw new BadRequestHttpException('"file" is required');        }


我得到的回应是:

data: {
      '@context': '/api/public/contexts/Error',
      '@type': 'hydra:Error',
      'hydra:title': 'An error occurred',
      'hydra:description': '"file" is required',
      trace: [Array]
    }


我不觉得我的要求有什么问题。
我试着发送到这个API进行测试:http://httpbin.org/post,它似乎工作正常。
为了弄清楚这是怎么回事,我有另一个项目与symfony(一个旧版本)。所以我添加了一个测试路由,以检查文件是否为空:

public function testUploadAction(Request $request) {
    $jsonConverter = new JsonConverter();
    print_r($request->files->get('file'));
    print_r($_FILES);
    print_r($_POST);
    $response = $jsonConverter->objectToJson([]);
    return $response;
}


下面是回应:

Symfony\Component\HttpFoundation\File\UploadedFile Object
(
    [test:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 
    [originalName:Symfony\Component\HttpFoundation\File\UploadedFile:private] => test.pdf
    [mimeType:Symfony\Component\HttpFoundation\File\UploadedFile:private] => application/pdf
    [size:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 138806
    [error:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 0
    [pathName:SplFileInfo:private] => /tmp/php6bG6bm
    [fileName:SplFileInfo:private] => php6bG6bm
)
Array
(
    [file] => Array
        (
            [name] => test.pdf
            [type] => application/pdf
            [tmp_name] => /tmp/php6bG6bm
            [error] => 0
            [size] => 138806
        )

)


所以我认为问题出在API上,然后我用一个rest工具(AdvancedRestClient)试了试,多么令人惊讶啊,我的文件成功上传了.
所以在这里,我认为有一些中间件或API上的东西正在删除我的文件,因为没有内容长度头。但我不能添加内容长度头,因为我正在发送流。
我尝试与

fs.statSync(filePath)['size'];


API检测我的文件,但我有经典的:

The uploaded file was only partially uploaded.


顺便说一下,我自己的Symfony测试也有这个错误,这似乎是正常的。

4xrmg8kj

4xrmg8kj1#

我终于找到了解决问题的办法,而且我走上了正轨。
我不知道为什么,但是我需要推送文件的客户端API绝对需要“Content-Length”头。
我几乎找到了正确的方法来使用它,但错过了一些错误。
在此之前,我试过:

await axios({
    method: 'post',
    url: url,
    data: form,
    headers: {
        "Authorization": "Bearer "+token, 
        ...form.getHeaders(),
        "Content-Length": fs.statSync(downloadPath)['size']
    }
})

字符串
但是这里的长度并不完全是好的。我需要像这样改变FromData中的长度:

form.append('file', stream, {
    filename: test.pdf,
    contentType: 'application/pdf',
    knownLength: fs.statSync(downloadPath)['size']
});


然后,我可以提取总的formData长度来使用它:

await axios({
    method: 'post',
    url: url,
    data: form,
    headers: {
        "Authorization": "Bearer "+token, 
        ...form.getHeaders(),
        "Content-Length": form.getLengthSync()
    }
})


两者长度的区别是:

fs.statSync(downloadPath)['size'] = 138806 Bytes
form.getLengthSync() = 139043 Bytes


希望有时间能帮到你:)

相关问题