Angular 8 не может прочитать ответ на запрос, если в нем был большой блоб - PullRequest
0 голосов
/ 13 февраля 2020

Я разрабатываю API, который имеет конечную точку для обновления таблицы с большим двоичным объектом (15 МБ или около того), этот API обновляет таблицу, а затем отвечает JSON.

Когда эта конечная точка получает небольшой двоичный объект (несколько байтов), angular может прочитать JSON и показать результат пользователю. Если эта конечная точка получает большой двоичный объект, кажется, что весь запрос завершается неудачно, как показывает firefox в консоли: enter image description here

Я не думаю, что это проблема CORS, потому что все другие запросы, которые я делаю к этому серверу, в порядке, даже этот запрос в порядке, если большой размер достаточно мал.

Я usgin Angular 8, Python 3 (с Flask) и Mysql, но я не думаю, что это проблема с базой данных или конфигурацией на стороне сервера (например, max_allowed_packet или innodb_log_file_size для mysql и client_max_body_size для nginx), поскольку сервер получает те же самые файлы в конечной точке вставки, и все в порядке. Если я сохраню файл размером 15 МБ, он будет успешным, но если я попытаюсь обновить этот файл другим файлом с точно таким же размером, появится сообщение об ошибке.

Еще одна вещь, которая заставляет меня поверить, что проблема не в на стороне сервера nginx журнал доступа показывает только успешные запросы (все ответили кодом 200)

Так что я думаю, что проблема может быть только Angular, но, поскольку он работает, если большой двоичный объект мал, у меня есть абсолютно не знаю, где может быть проблема.

Вот служба, которая делает запрос: (вставка отлично работает со всеми размерами 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

1 Ответ

0 голосов
/ 14 февраля 2020

Судя по добавленному ответу OPTIONS, похоже, что вы неправильно устанавливали заголовок Access-Control-Allow-Origin в ответе сервера на запрос CORS OPTIONS.

Попробуйте установить Access-Control-Allow-Origin: * в ответе сервера на проверьте, не является ли проблема CORS, а затем замените подстановочный знак * на соответствующий источник, который вы будете использовать для предотвращения потенциально злонамеренных запросов перекрестного происхождения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...