2014-07-18 14 views
18

Tôi đang làm việc với API tùy chỉnh để cho phép người dùng tải lên tệp (có kích thước tùy ý). Nếu tập tin lớn, nó sẽ được chunkfied, và xử lý trong nhiều yêu cầu đến máy chủ.Phương thức HTML5 File.slice thực sự đang làm gì?

Tôi đang viết mã sử dụng FileFileReader (HTML5) theo nhiều ví dụ từ trực tuyến. Nói chung (từ những gì tôi đọc trên mạng) cho một chuyển tập tin chunkfied, đầu tiên mọi người sẽ nhận được một blob dữ liệu từ đối tượng tập tin của họ

var file = $('input[type=file]')[0].files[0]; 
var blob = file.slice(start,end) 

Sau đó sử dụng một FileReader để đọc blob readAsArrayBuffer(blob) hoặc readAsBinaryString(blob)

Và cuối cùng trong phương thức FileReader.onload(e), gửi dữ liệu đến máy chủ. Lặp lại quá trình này cho tất cả các khối trong tập tin.

Câu hỏi của tôi là

Tại sao tôi cần phải sử dụng một FileReader? Nếu tôi không sử dụng nó, và chỉ cần gửi các đốm màu với File.slice, có bất kỳ đảm bảo rằng hoạt động cắt sẽ được thực hiện trước khi tôi cố gắng gửi dữ liệu trong mỗi yêu cầu. Đối tượng File có tải toàn bộ tệp khi được tạo (chắc chắn không?). File.slice tìm đến vị trí được quy định bởi các tham số, và sau đó đọc thông tin trong? Tài liệu không cung cấp cho tôi manh mối về cách nó được triển khai.

Trả lời

21

Điều quan trọng cần lưu ý là Tệp được kế thừa từ Blob, Tệp không thực sự có phương thức lát, nó nhận phương thức này từ Blob. Tệp chỉ thêm một vài thuộc tính siêu dữ liệu.

Cách tốt nhất để nghĩ về Blob (hoặc Tệp) là con trỏ đến dữ liệu, nhưng không phải là dữ liệu thực tế. Sắp xếp giống như một tập tin xử lý bằng các ngôn ngữ khác.

Bạn thực sự không thể truy cập dữ liệu trong Blob mà không sử dụng trình đọc đọc không đồng bộ để tránh chặn chuỗi giao diện người dùng. Phương thức Blob slice() chỉ trả về một Blob khác, nhưng một lần nữa, đây không phải là dữ liệu, nó chỉ là một con trỏ tới một phạm vi dữ liệu trong Blob gốc, giống như một con trỏ bị giới hạn cho một khung nhìn. Để thực sự lấy các byte ra khỏi Blob đã cắt, bạn vẫn cần sử dụng một trình đọc. Trong trường hợp của một đốm màu thái lát, đầu đọc của bạn bị chặn lại. Điều này thực sự chỉ là một tiện lợi để bạn không phải mang theo một loạt các khoảng cách tương đối và tuyệt đối xung quanh trong mã của bạn, bạn chỉ có thể có được một cái nhìn giới hạn của dữ liệu và sử dụng trình đọc như thể bạn đang đọc từ byte 0.

Trong trường hợp của XMLHttpRequest (giả sử trình duyệt hỗ trợ giao diện mới hơn), dữ liệu sẽ được phát trực tuyến khi gửi và bị hạn chế bởi các giới hạn của đốm màu. Về cơ bản, nó sẽ làm việc giống như cách bạn tưởng tượng nó hoạt động nếu bạn gửi một con trỏ tập tin đến một phương thức luồng (mà về cơ bản là những gì đang diễn ra dưới các nắp). https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Sending_binary_data

Về cơ bản, đó là một người đọc lười biếng. Nếu blob đã được tải/đọc từ hệ thống tập tin, hoặc được tạo ra trong bộ nhớ, nó sẽ chỉ sử dụng nó. Tuy nhiên, khi bạn sử dụng Tệp, tệp sẽ được tải và tải xuống không đồng bộ một cách không đồng bộ trong chuỗi chính.

Logic cơ bản ở đây là trình duyệt không bao giờ muốn đọc đồng bộ vì nó có thể chặn luồng chính, vì vậy tất cả các API được thiết kế xung quanh triết lý cốt lõi đó. Chú ý cách Blob.slice() là đồng bộ - đó là cách bạn biết nó không thực sự làm bất kỳ IO, nó chỉ là thiết lập giới hạn và (có thể) tập tin con trỏ.

+1

Cảm ơn bạn đã xác định Tệp cho tôi, điều đó có ý nghĩa hơn nhiều. Tuy nhiên, nếu tôi vẫn sử dụng File.Slice (trả về một blob), và sau đó thử gửi blob đó đến máy chủ bằng cách sử dụng XMLHttpRequest.send (myBlob), dữ liệu được lấy ra từ tệp đó như thế nào và khi nào được cung cấp cho máy chủ . Hoặc điều này sẽ thất bại/không gửi bất kỳ dữ liệu nào? - – Ponml

+0

Tôi đã cập nhật câu trả lời của mình để cung cấp thêm một chút chi tiết. Tôi đã tham gia vào công cụ này khá sâu sắc khi tôi đang viết tiện ích rsync javascript của mình: https://github.com/claytongulick/bit-sync –

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