【问题标题】:How to angular2 post JSON data and files In same request如何 angular2 在同一请求中发布 JSON 数据和文件
【发布时间】:2017-02-03 06:33:54
【问题描述】:

我想在同一个请求中实现 post 文件和 Json 数据。

以下是上传文件代码:

upload(url:string,file:File):Observable<{complate:number,progress?:number,data?:Object}>{


    return Observable.create(observer => {
      const formData:FormData = new FormData(),
        xhr:XMLHttpRequest = new XMLHttpRequest();
      formData.append('uploadfile', file);


      formData.append("_csrf", this.tokenService.getCsrf());
      xhr.open('POST',url, true);
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            observer.next({complate:1,progress:100,data:JSON.parse(xhr.response)});
            observer.complete();
          } else {
            observer.error(xhr.response);
          }
        }
      };

      xhr.upload.onprogress = (event) => {
        observer.next({complate:0,progress:Math.round(event.loaded / event.total * 100)});
      };


      const headers=new Headers();
      let token: string = localStorage.getItem('access-token');
      xhr.setRequestHeader('Authorization', `Bearer ${token}`);
      xhr.send(formData);
    }).share();

如何与 angular2 集成 http.post(url, JSON.stringify(data)).

【问题讨论】:

  • angular2 目前不支持 http.post 中的文件:github.com/angular/http/issues/75 但您仍然可以使用 arraybufferBlob 发送文件。另外,要实现进度,请检查以下答案:stackoverflow.com/a/37159100/4102561
  • 使用Blob?有例子吗?
  • 我没有示例,但它需要非常复杂的操作(从表单中获取文件、从文件中创建 blob、将 blob 添加到表单等)。我认为您的解决方案是目前最好的解决方案。 (仅使用基本 xhr 请求)。
  • 我也面临同样的问题。我需要提交带有文本和文件数据的表单。有什么方法可以在 Angualr JS 2 中实现?

标签: angular typescript file-upload


【解决方案1】:

所以我也一直在尝试这样做,对于看起来非常简单的事情,我最终很难找到解决方案。希望一些同事帮助我,我们想出了一些合理的东西。

这份文档对我们帮助很大:https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects

这是 Angular 代码:

class SomeService {
  someMethod(fileToUpload: File, name: string, version: string) {
    const formData: FormData = new FormData();
    formData.append('file', fileToUpload, fileToUpload.name);

    const overrides = {
      name,
      version,
    };

    const blobOverrides = new Blob([JSON.stringify(overrides)], {
      type: 'application/json',
    });

    formData.append('overrides', blobOverrides);

    const req = new HttpRequest('POST', `some-url`, formData);

    return this.http.request(req);
  }
}

正如@Supamiu 所说,使用 Blob 是关键,这里有一个示例。

【讨论】:

  • 嗨@Maxime 你应该如何解析后端的 JSON 数据?
  • 很抱歉那个布赖恩,但我不是负责那个,甚至不再在这家公司工作了。祝你好运
  • 不用担心,感谢@Maxime 的前端回答:)
【解决方案2】:

以下客户端和服务代码在我的解决方案中运行良好,检查是否有帮助

客户端代码:

    AddModelData(modelData: ModelData, file: any): Observable<any> 
    {
      let urlPath = 'api/SampleActionMethod/AddModelData';
      const mData = JSON.stringify(modelData);
      const formData = new FormData();
      formData.append('data', mData);
      if (file) {
        formData.append('file', file, file.name);
      }
      return this._http.post(this.settings.apiEndPoint + urlPath, formData);
    }

服务端代码:

public IActionResult PostMethod(IFormFile file)
{      
  try
  {                
    var modelData = JsonConvert.DeserializeObject<ModelData>(Request.Form["data"]); 
    //data is the key that is being passed from client side
    //file in params will have the posted file

    //Do Something with data and file......

    return Ok();
  }
  catch (Exception e)
  {
    return StatusCode(500, e.Message);
  }
}

【讨论】:

  • 很好的解决方案。有人认为我注意到了,我们不需要 API 级别的 IFormFile 有效负载,可以从 HttpRequest 中检索值。
【解决方案3】:
//app.component.html

<input type="file" name="file" (change)="onChange($event)">
<button (click)="onSubmisson()" [disabled]="file==null" >Submit</button>

//app.component.ts

file:File = null;

onChange(event){
 this.file = event.target.files[0]
}

onSubmisson(){
 this._auth.uploadFileAndData(this.file).subscribe(
 res => {
    console.log(res);
 },err => {
    console.log(err);
 });
}

//upload.service.ts

uploadFileAndData(file){
  var test = {test:"test"}
  const formData = new FormData();
  formData.append('data', JSON.stringify(test));
  formData.append('file', file, file.name);
  return this._http.post<any>(this._uploadurl, formData);
}

//node server

var multer = require('multer');
var path = require('path');

var storage = multer.diskStorage({
  // destination
  destination: function (req, file, cb) {
    cb(null, './uploads/')
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname);
  }
});

var upload = multer({ storage: storage }).array("file", 12);

router.post("/upload",  function(req , res){
    upload(req, res, function (err) {
        if(err){
            console.log(err);
        }else{
            console.log(req.body);
            console.log('files', req.files);
        }
    })
    res.status(200).send({});
});

// output

{ data: '{"test":"test"}' }

files [ { fieldname: 'file',
    originalname: 'acfcdea5-28d2-4f2e-a897-1aef3507193d.jpg',
    encoding: '7bit',
    mimetype: 'image/jpeg',
    destination: './uploads/',
    filename: 'acfcdea5-28d2-4f2e-a897-1aef3507193d.jpg',
    path: 'uploads\\acfcdea5-28d2-4f2e-a897-1aef3507193d.jpg',
    size: 49647 } ]

【讨论】:

    【解决方案4】:

    我的经理@Jesse 的想法是这样的:

    public uploadFiles(id: ServerID, brd: File, sch: File, args: any[]): Observable<Blob> {
            const data = new FormData();
            data.append('brd', brd);
            data.append('sch', sch);
            data.append('data', JSON.stringify(args));
            return this.httpClient.post(URL, data, {
                responseType: 'blob',
            });
        }
    

    FormData append() 的定义是 append(name: string, value: string | Blob, fileName?: string): void;,它允许您向其附加 JSON 参数或上传文件。

    【讨论】:

      猜你喜欢
      • 2017-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-15
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 2017-03-26
      相关资源
      最近更新 更多