Angular - 将文件上传为base64

rea*_*dow 8 rest base64 json file-upload angular

我正在尝试将文件从Angular 4应用程序上传到JSON API服务,该服务接受base64字符串作为文件内容.

所以我所做的是 - 用文件读取FileReader.readAsDataURL,然后当用户确认上传时,我将向API创建一个JSON请求并发送base64我之前获得的文件的字符串.

这就是问题开始的地方 - 只要我对"内容"(记录,发送,w/e)执行某些操作,请求将被发送,但其速度非常慢,例如20MB的2MB文件.

我试过了:

  • 使用ArrayBuffer并手动将其转换为base64
  • 将base64字符串存储在HTML中并稍后检索
  • 用户点击上传按钮后读取文件
  • 使用旧客户端 @angular/common
  • 使用普通的XHR请求

但是一切都会导致相同的结果.

我知道问题所在.但为什么会这样呢?是浏览器特定的还是角度特定的?是否有更优选的方法(请记住它必须是base64字符串)?


笔记:

  • 更改API中的任何内容都超出了我的控制范围
  • API很好,通过postman发送任何文件将立即完成

码:

当用户将文件添加到dropzone时,此方法将运行:

public onFileChange(files: File[]) : void {
    files.forEach((file: File, index: number) => {
        const reader = new FileReader;

        // UploadedFile is just a simple model that contains filename, size, type and later base64 content
        this.uploadedFiles[index] = new UploadedFile(file);

        //region reader.onprogress
        reader.onprogress = (event: ProgressEvent) => {
            if (event.lengthComputable) {
                this.uploadedFiles[index].updateProgress(
                    Math.round((event.loaded * 100) / event.total)
                );
            }
        };
        //endregion

        //region reader.onloadend
        reader.onloadend = (event: ProgressEvent) => {
            const target: FileReader = <FileReader>event.target;
            const content = target.result.split(',')[1];

            this.uploadedFiles[index].contentLoaded(content);
        };
        //endregion

        reader.readAsDataURL(file);
    });
}
Run Code Online (Sandbox Code Playgroud)

用户单击"保存"按钮时会运行此方法

public upload(uploadedFiles: UploadedFile[]) : Observable<null> {
    const body: object = {
        files: uploadedFiles.map((uploadedFile) => {
            return {
                filename: uploadedFile.name,
                // SLOWDOWN HAPPENS HERE
                content: uploadedFile.content
            };
        })
    };

    return this.http.post('file', body)
}
Run Code Online (Sandbox Code Playgroud)

Yas*_*ser 4

为了将大文件发送到服务器,您应该使用FormData能够将其作为多部分而不是单个大文件发送。

就像是:

// import {Http, RequestOptions} from '@angular/http';
uploadFileToUrl(files, uploadUrl): Promise<any> {
  // Note that setting a content-type header
  // for mutlipart forms breaks some built in
  // request parsers like multer in express.
  const options = new RequestOptions();
  const formData = new FormData();

  // Append files to the virtual form.
  for (const file of files) {
    formData.append(file.name, file)
  }
  // Send it.
  return this.http.post(uploadUrl, formData, options);
    
}
Run Code Online (Sandbox Code Playgroud)

另外不要忘记设置标题'Content-Type': undefined,我已经为此绞尽脑汁好几个小时了。