2010-01-03 28 views
6

trong dự án của tôi, tôi cho phép người dùng chọn ảnh bằng cách sử dụng lớp FileReference. Sau đó tôi tải các ảnh này vào các thuộc tính .data của chúng, sử dụng hàm load(). Sau này tôi thực hiện một số thao tác cục bộ và gửi chúng đến máy chủ.Flex: DeepCopy của FileReference

Điều tôi muốn làm là có khả năng lặp lại qua các FileReferences đã chọn, tải chúng vào các thuộc tính .data, thực hiện thao tác khác và gửi chúng đến máy chủ một lần nữa. Tôi biết rằng tôi sẽ có thể thực hiện điều này từ sự kiện do người dùng gọi, đó không phải là vấn đề ở đây.

Vấn đề là, khi FileReference được tải lần đầu tiên, tôi không thể dỡ bỏ nó theo bất kỳ cách nào, và tôi không thể giữ dữ liệu cho tất cả các ảnh trong bộ nhớ vì chúng rất lớn. Vì vậy, tôi đoán rằng chỉ có một điều tôi có thể làm, đó là thực hiện một DeepCopy trên FileReference ... Sau đó tôi có thể tải phiên bản đầu tiên, phế liệu nó và sử dụng bản sao cho lần thứ hai 'chạy'.

Tôi đã cố gắng sử dụng ObjectUtil.copy, nhưng khi tôi truy cập ví dụ: tài sản .name của bản sao, nó không thành công với:

Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful. 

vào tên flash.net::FileReference/get()

đoạn có liên quan:

registerClassAlias("FileReference",FileReference); 
masterFileList.addItem(FileReference(ObjectUtil.copy(fr_load.fileList[i]))); 
trace(masterFileList[i].name) 

Có đúng là có một số thuộc tính được bảo vệ của lớp FileReference có thể ngăn không cho nó được sao chép? Nếu nó là như vậy, tôi có thể bỏ qua điều này bằng cách nào đó? Hoặc là có bất kỳ giải pháp khác cho vấn đề tổng thể của tôi?

Tôi đánh giá cao bất kỳ gợi ý/ý tưởng nào!

+0

Tôi mang nó lên tại actionscript.org và được xây dựng thêm một chút, nhưng vẫn không có hy vọng. Dù sao ở đây là chủ đề: http://www.actionscript.org/forums/showthread.php3?t=227441 – supo

+0

Tôi đoán điều này không thể được thực hiện, vì có lẽ một số xử lý trong đối tượng FileReference không thể truy cập được sử dụng ActionScript. Tôi sẽ không ngạc nhiên nếu lớp FileReference thậm chí không được triển khai trong ActionScript. –

Trả lời

1

bạn không thể sử dụng ObjectUtil.copy. Phương pháp này được thiết kế để sao chép các đối tượng dữ liệu duy nhất (các lớp VO).

bạn nên tạo một FileReference mới và sao chép từng phần một. Tạo một chức năng để làm điều này ..

+0

Xin chào, cảm ơn câu trả lời. Nhưng bạn đã bao giờ thử sao chép đối tượng FileReference như thế chưa? Tôi có nghĩa là, các thuộc tính quan trọng có thể được bảo vệ và một khi được công khai xuất hiện để được đọc chỉ. Bạn chỉ có thể truy cập .data sau khi tải() FR, vì vậy bạn có thể sao chép dữ liệu sau này. Nhưng đây không phải là điều tôi muốn. Tôi cần phải sao chép nó trước khi tải nó. Bằng cách này tôi có thể tải nó trong lần chạy đầu tiên và trong lần chạy thứ hai một cách riêng biệt. – supo

1

Sao chép tệp đó vào một tệp tạm thời và sau đó tải lên tệp tạm thời hoạt động? Ví dụ:

 var fileRef:FileReference = new FileReference(); 
     fileRef.browse(); 

     ...................... 

     var tmpFile:File = File.createTempFile(); 
     try { 
      var tmpFileStream:FileStream = new FileStream(); 
      tmpFileStream.open(tmpFile, FileMode.WRITE); 
      trace("Opened file: " + tmpFile.nativePath); 
      tmpFileStream.writeBytes(fileRef.data); 
      trace("copied file"); 
     } catch (error:Error) { 
      trace("Unable to open file " + tmpFile.nativePath + "\n"); 
      throw error; 
     } 
+0

Bạn có đề xuất lưu trữ tất cả các hình ảnh với chất lượng đầy đủ trong bộ nhớ và sau đó tải lên từ bộ nhớ không? Điều đó sẽ không giúp được gì, bởi vì ngay cả số lượng nhỏ các hình ảnh (như 10) thậm chí không có chất lượng tốt nhất (cho phép nói 3MB/mỗi) mất vài trăm megabyte RAM, ngay cả khi tôi mã hóa chúng thành JPEG và lưu trữ sau đó. Và tôi muốn làm việc với 100 hình ảnh trở lên. – supo

+0

Hmm đợi một giây, bây giờ tôi thấy rằng bạn đang tạo một tệp ở đó. Không phải là createTempFile ràng buộc với AIR? Tôi đã không đề cập đến nó, nhưng đây không phải là một ứng dụng AIR. – supo

1

Tôi nghĩ rằng thao tác này hoàn toàn không được phép, vì lý do tốt. Nếu bạn có thể sao chép một FileReference mới thông qua mã ActionScript, thì bạn cũng có thể tạo ra một đối tượng FileReference thông qua mã ActionScript. Tất nhiên, đó sẽ là một lỗ hổng bảo mật khá tệ nếu bạn có thể buộc tải lên một tệp tùy ý.

Giữ một bản sao của dữ liệu trong bộ nhớ thực sự không phải là xấu của một giải pháp. Xét cho cùng, đó là tạm thời. Máy khách điển hình sẽ có thể quản lý thêm vài trăm MB dữ liệu mà không có vấn đề gì. Đó chắc chắn là một lựa chọn tốt hơn so với việc trình duyệt của họ thực hiện hai lần tải lên riêng biệt, đó là những gì mà giải pháp đã thử của bạn sẽ kết thúc.

Một giải pháp tiềm năng hoàn toàn khác cho vấn đề này là tránh hoàn toàn thao tác hình ảnh bằng Flex. Flex có thể đăng tải tệp trực tiếp lên máy chủ và máy chủ có thể tự thực hiện thao tác hình ảnh. Tất nhiên, nếu thao tác được điều khiển thông qua tương tác của người dùng, thì điều đó sẽ không hiệu quả chút nào.

+0

Vài trăm MB nữa? AFAIK không có cách nào tôi có thể lưu trữ 1 hình ảnh trong ít hơn 50 MB RAM. Những hình ảnh này là jpeg và trọng lượng khoảng 1-5MB khi được nén trên đĩa. Tôi muốn làm việc với 100 hình ảnh ít nhất, làm cho nó 5GB RAM, mà không được chấp nhận bởi bất kỳ phương tiện. Cách thay thế khác mà bạn đề xuất cũng xảy ra với tôi. Thao tác không phải do người dùng điều khiển, NHƯNG cách tiếp cận này sẽ yêu cầu người dùng đợi cho đến khi tất cả các hình ảnh được tải lên với chất lượng tốt và điều này có thể mất một giờ. Tôi không muốn buộc người dùng phải chờ đợi lâu trong phần đầu công việc của mình với ứng dụng .. – supo

+0

Nếu bạn có thể đề xuất cách LÀM THẾ NÀO để lưu trữ hình ảnh trong RAM hiệu quả hơn, điều đó sẽ thật tuyệt. Cho đến nay tôi đã thử các bitmap cơ bản là ngu ngốc và sau đó tôi đã thử mã hóa chúng thành Jpeg và lưu trữ chúng dưới dạng các byte. – supo

+0

Bạn sẽ không phải lưu trữ tất cả hàng trăm bức ảnh cùng một lúc. Bạn có thể xử lý chúng cùng một lúc, phát hành bộ đệm tạm thời sau khi bạn kết thúc với từng bộ đệm. – Jacob

1

Tôi đã cố gắng làm gần như chính xác những gì bạn đang làm, và tôi gần như đã từ bỏ sau khi đọc một số câu trả lời, nhưng tôi nghĩ tôi đã tìm ra cách để làm điều đó.Tôi đã thấy rằng nếu bạn có một đối tượng FileReference, nếu bạn gọi load() nhiều lần, nó sẽ hoạt động, nhưng vấn đề chính là bạn đang giữ các byte có độ phân giải cao trong bộ nhớ sau lần tải đầu tiên. Như bạn đã đề cập, đối với những người không biết xử lý hình ảnh, đây là một không lớn.

Cách để giải quyết vấn đề này là sau load() đầu tiên, bạn cần gọi phương thức cancel() trên FileReference. Từ thử nghiệm của tôi cho đến nay, có vẻ như điều đó sẽ xóa các byte trong FileReference và load() sẽ vẫn hoạt động nếu bạn gọi nó lần thứ hai sau đó. Tôi đã thử nó trên hệ thống của tôi cho đến nay, nhưng nó hoạt động tốt ở đó. Chỉ cần một lời cảnh cáo, đây không phải là hành vi được xác định rõ ràng trong API, do đó, nó chắc chắn có thể thay đổi, nhưng nó có thể giúp bạn có được nơi bạn cần phải đi trong thời gian có nghĩa là.

Hy vọng điều đó sẽ hữu ích.