2017-12-02 30 views
8

Tôi đang cố gắng tải tệp từ ứng dụng Angular 4 lên dịch vụ JSON API chấp nhận chuỗi base64 làm nội dung tệp. Vì vậy, những gì tôi làm là - đọc tập tin với FileReader.readAsDataURL, sau đó khi người dùng xác nhận tải lên, tôi sẽ tạo một yêu cầu JSON tới API và gửi chuỗi base64 của tệp mà tôi nhận được trước đó.Góc - tải lên tệp dưới dạng base64

Đây là nơi mà vấn đề bắt đầu - ngay sau khi tôi làm điều gì đó với "nội dung" (đăng nhập nó, gửi nó, w/e) yêu cầu sẽ được gửi, nhưng nó điên cuồng chậm, ví dụ 20 giây cho tệp 2MB.

Tôi đã thử:

  • sử dụng ArrayBuffer và tự chuyển đổi nó sang base64
  • lưu trữ các chuỗi base64 trong HTML và lấy nó sau này
  • đọc các tập tin sau khi người dùng nhấp vào nút tải lên
  • sử dụng ứng dụng khách cũ từ @angular/common
  • sử dụng yêu cầu XHR đơn giản

nhưng mọi thứ đều dẫn đến cùng một kết quả.

Tôi biết vấn đề nằm ở đâu. Nhưng tại sao nó xảy ra? Có một cái gì đó cụ thể của trình duyệt hoặc góc cụ thể không? Có một cách tiếp cận ưa thích hơn (ghi nhớ nó phải là chuỗi base64)?


Ghi chú:

  • thay đổi bất cứ điều gì trong API là ngoài tầm kiểm soát của tôi
  • API được tốt, gửi bất kỳ người đưa thư tập máng sẽ kết thúc ngay lập tức

Mã số:

Phương pháp này chạy khi người dùng thêm file vào vùng thả:

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); 
    }); 
} 

Phương pháp này chạy khi người dùng nhấp chuột nút lưu

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) 
} 
+0

Bạn đang hỏi về vấn đề với mã của mình, nhưng bạn không đăng bất kỳ dòng nào của nó. –

+0

@JB Nizet Tôi đã thêm mã có liên quan – realshadow

+0

Điều gì xảy ra nếu bạn tự xây dựng chuỗi JSON bằng cách nối chuỗi đơn giản (vì bạn biết rằng base64 không chứa bất kỳ ký tự nào phải được mã hóa), thay vì để http làm điều đó? –

Trả lời

3

Đối với việc gửi các tập tin lớn đến máy chủ bạn nên sử dụng FormData để có thể gửi nó dưới dạng nhiều phần thay vì một tệp lớn duy nhất.

Cái gì như:

// 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); 
 
    
 
}

Cũng đừng quên đặt tiêu đề 'Content-Type': undefined, tôi đã gãi đầu của tôi trên này nhiều giờ.

+0

Điều này không giải quyết được vấn đề của tôi vì tôi không thể thay đổi API.Tôi biết rằng điều này có vẻ là giải pháp duy nhất vì vậy tôi chỉ tìm kiếm câu trả lời cho lý do tại sao phải mất rất nhiều thời gian để xử lý yêu cầu. anyway – realshadow

+0

Trong trường hợp đó, hãy nhớ rằng điều duy nhất mà bạn nghĩ đến là sử dụng http compression/deflate @realshadow – Yaser

Các vấn đề liên quan