首页 > 解决方案 > 如何将文件和 JSON 数据发送到服务器

问题描述

tl;dr:在前端使用 Angular 6,在后端使用 PHP 和 Phalcon,我可以毫无问题地发送 JSON 数据或文件,但在同一个请求中发送两者时出现问题。


以前我使用类似这样的东西将 JSON 数据发送到服务器

const HTTP_OPTIONS = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
  }),
  observe: 'response'
};

post(endPoint: string, body: object): Observable<any> {
    return this.http.post<any>(this.apiUrl + endPoint, body, HTTP_OPTIONS)
      .pipe(
        tap(result => this.log(JSON.stringify(result, null, 2))),
        catchError(this.handleError('post', []))
      );
}

我能够使用 Phalcon 从 PHP 获取数据

$app = new \Phalcon\Mvc\Micro();
$app->post('/upload', function() use ($app) {

    $input = $app->request->getJsonRawBody();
    // $input now contains my JSON data
});

一段时间后,我需要发送一个文件,所以我用这个答案做了一些小的修改:

postFile(fileToUpload: File, endpoint: string): Observable<any> {
    const formData: FormData = new FormData();
    formData.append('fileKey', fileToUpload, fileToUpload.name);
    return this.httpClient
      .post(endpoint, formData, { headers: {'Authorization': this.jwt} }).pipe(
        tap(result => this.log(JSON.stringify(result, null, 2))),
        catchError(this.handleError('post', []))
      );
  }

我使用文档作为指南收到了我的文件,没有任何问题:

$app->post('/uploads', function() use ($app) {
    if ($app->request->hasFiles() == true) {
        foreach ($app->request->getUploadedFiles() as $file) {
            $file->moveTo('files/' .$file->getname());
        }
    } else {
      $app->response->setStatusCode(400)->sendHeaders();
      $app->response->setJsonContent(['error' => 'no file']);
      return $app->response;
    }
});

问题:现在我想同时发送一个文件和一些 JSON 数据。我总是可以只上传文件然后单独发送数据,但我认为这不是正确的方法。我不想进行超过最低数量的网络调用。

我试过的:使用文件上传代码并简单地将另一个字段与我的 JSON 数据附加到我的 FormData 对象

formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', JSON.stringify(data));

以及它的变体

formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', new Blob([JSON.stringify(data), {type: 'application/json'}]);

无论哪种方式,在后端我都可以获取文件,但$app->request->getJsonRawBody$app->request->getRawBody是空的。

我还尝试使用原始的 JSON 发送代码,只是稍作更改以包含该文件,但没有成功。

post(fileToUpload: File, data: CustomData): Observable<any> {
    this.messageService.add('uploaded file');

    const formData: FormData = new FormData();
    formData.append('fileKey', fileToUpload, fileToUpload.name);
    formData.append('data', JSON.stringify(data), 'data');

    return this.http
      .post(this.apiUrl + 'uploads/', {'data': data, 'file': fileToUpload}, HTTP_OPTIONS).pipe( // file is empty on the server like this
        tap(result => this.log('POST file :\n' + JSON.stringify(result, null, 2))),
        catchError(this.handleError('post', [], 'fileUpload'))
      );
  }

我可以轻松地发送我的 JSON 数据或文件,但不能同时发送两者。我搜索了 Phalcon 文档和几个关于使用 Angular 发送文件和/或 JSON 的 QA,但我不知道如何使它工作。

标签: phpangularuploadphalconangular-httpclient

解决方案


您在 post 请求中将 json 作为文本发送,因此您应该尝试类似的方法,而不是 $app->request->getJsonRawBody

$rawJson=$app->request->getPost('data');
$object=json_decode($rawJson);

推荐阅读