javascript - 如果请求中有大块,Angular 8 无法读取响应
问题描述
我正在开发一个 API,它有一个端点来更新一个带有大 blob(15MB 左右)的表,这个 api 更新表然后用 JSON 响应。
当此端点接收到一个小 blob(几个字节)时,angular 可以读取 JSON 并向用户显示结果。如果此端点接收到一个大 blob,则似乎整个请求都失败了,如 Firefox 在控制台中显示的那样:
我认为这不是 CORS 问题,因为我向该服务器发出的所有其他请求都可以,如果 blob 足够小,即使此请求也可以。
我正在使用 Angular 8、Python 3(带有 Flask)和 Mysql,但我认为这不是数据库或服务器端配置的问题(例如 mysql 的 max_allowed_packet 或 innodb_log_file_size 和 nginx 的 client_max_body_size),因为服务器接收到这些插入端点中的文件完全相同,一切都很好。如果我保存一个 15MB 的文件,它是成功的,但如果我尝试用另一个大小完全相同的文件更新该文件,则会出现错误。
让我相信问题不在服务器端的另一件事是 nginx 访问日志仅显示成功的请求(均以代码 200 响应)
所以我认为问题只能是 Angular,但是如果 blob 很小,它就可以工作,我完全不知道问题可能出在哪里。
这是发出请求的服务:(插入适用于所有大小的 blob,仅使用小 blob 更新)
export class documentService {
constructor(private http: HttpClient, private toastr: ToastrService) { }
insert(file:File, tags:Tag[], permitions:User[], extraFields:any, type:string){
const formData = new FormData();
formData.append('tags', JSON.stringify(tags));
formData.append('permitions', JSON.stringify(permitions));
formData.append('binary_data', file);
formData.append('extraFields', JSON.stringify(extraFields))
return this.http.post<Resposta>(SERVER+"/document/"+type, formData, {"reportProgress": true})
}
update(file:File, tags:Tag[], permitions:Usuario[], docId, extraFields:any, type:string){
const formData = new FormData();
formData.append('tags', JSON.stringify(tags));
formData.append('permitions', JSON.stringify(permitions));
formData.append('binary_data', file);
formData.append('extraFields', JSON.stringify(extraFields))
return this.http.put<Resposta>(SERVER+"/document/"+type+"/"+docId, formData, {"reportProgress": true})
}
}
这是使用上述服务的组件部分:
this.docService.update(file, tags, permitions, this.doc.id,this.doc, TYPES.INTERNAL).subscribe( r => {
if(!r.error){
this.setEditMode(false)
this.hide()
}
})
而且我还有一个拦截器:
export class ApiInterceptor implements HttpInterceptor {
constructor(private toastr: ToastrService, private progress: ShowProgressService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let newHeaders = { 'Authorization': localStorage.getItem('jwt') || ""}
const cloneReq = req.clone({
setHeaders: newHeaders
});
return next.handle(cloneReq).pipe(
tap((event: any)=>{
if(event.body && event.body.msg && event.body.error!=undefined){
if(event.body.error){
this.toastr.error(event.body.msg)
} else{
this.toastr.success(event.body.msg)
}
}
// shows upload progress
if(event.type === HttpEventType.UploadProgress){
let percentDone = Math.round((100 * event.loaded) / event.total);
this.progress.showUpload(percentDone)
}
if(event.type === HttpEventType.DownloadProgress){
let percentDone = Math.round((100 * event.loaded) / event.total);
this.progress.showDownload(percentDone)
}
})
);
}
}
编辑 1 - 选项请求:
要求:
Host: url
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: */*
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: authorization
Referer: http://url/dashboard
Origin: http://url
DNT: 1
Connection: keep-alive
回复:
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Thu, 13 Feb 2020 20:30:39 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Allow: GET, HEAD, PUT, OPTIONS, DELETE
Access-Control-Allow-Origin: http://url
Vary: Origin
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
解决方案
根据您添加的 OPTIONS 响应,您似乎没有正确设置Access-Control-Allow-Origin
服务器对 CORS OPTIONS 请求的响应中的标头。
尝试Access-Control-Allow-Origin: *
在服务器的响应中设置以查看 CORS 是否是问题,然后将*
通配符替换为您将使用的适当来源,以防止潜在的恶意跨来源请求
推荐阅读
- reactjs - 使用 Redux Persist 触发时复选框 UI 未更改
- sql - 在没有 DISTINCT 的 Postgres 中使用 LEFT JOIN 时防止重复行
- uisearchcontroller - 在 Xcode 12 中将 UISearchDisplayController 迁移到 Objective-c 中的 UISeachController
- python-3.x - json输出到客户端的异步流和同步流之间的区别
- clojure - clojure 中的 def 是保存函数的返回值还是每次都会对函数进行评估?
- r - 如何在 x 轴的每一侧制作条形图
- json - BigQuery json 函数 - 如果 json 字符串格式不正确,则无法提取所有值
- reactjs - 如何在函数中传递 onChange 和 props
- google-apps-script - 共享 Google 数据洞察连接器,但不允许对脚本进行只读访问
- swift - 从具有不同背景选项的同一 iOS 应用程序投射音乐和视频不起作用