9

Đây là những gì tôi đang làm. Tôi muốn tải lên tệp nhiều phần thông qua Ajax vào ứng dụng web mùa xuân của tôi. Khi máy chủ nhận được yêu cầu POST, nó sẽ tạo một số vé trong cơ sở dữ liệu. Sau đó, nó bắt đầu một chuỗi xử lý việc tải tệp lên thực tế. Máy chủ sau đó trả về số vé.Tải lên tệp không đồng bộ trong Spring

Tôi đang sử dụng CommonsMultipartResolver để xử lý yêu cầu và tôi đã đặt cờ resolveLazily thành true để Multipart không được giải quyết ngay lập tức.

Vì vậy, đây là một cái gì đó dọc theo dòng của những gì tôi có

@Controller 
public class myController{ 

    @RequestMapping(value = "/upload", method = RequestMethod.POST) 
    @ResponseStatus(value = HttpStatus.OK) 
    @ResponseBody 
    public String upload(MultipartHttpServletRequest request, String fileName){ 

     String ticket = dao.createUploadTicket(fileName); 
     Runnable run = new Runnable(){ 

      @Override 
      public void run(){ 

       dao.writeUpdate(ticket, "Getting data from request"); 
       final MultipartFile file = request.getFile("theFile"); 
       dao.writeUpdate(ticket, "Multipart file processed"); 
       try { 
        dao.writeUpdate(ticket, "Saving file to disk"); 
        file.transferTo(new File("/myDirectory")); 
        dao.writeUpdate(ticket, "File saved to disk"); 
       } 
       catch(Exception e){ 
        dao.writeUpdate(ticket, "File upload failed with the exception " + e.toString()); 
       } 
      } 
     }; 
     Thread t = new Thread(run); 
     t.start(); 
     return ticket; 
    } 
} 

Vì vậy, các điểm ở đây là số lượng vé có thể được sử dụng để có được những thông tin cập nhật tiến độ. Giả sử một tệp lớn đang được tải lên. Khách hàng đã thực hiện tải lên tệp POST (ví dụ trong trường hợp này là một yêu cầu Ajax) có thể làm điều đó một cách không đồng bộ và lấy lại một số vé. Khách hàng có thể sử dụng số vé đó để xác định giai đoạn tải lên tệp và hiển thị thông tin trong một trang khác.

Một cách sử dụng khác là tôi có thể có trang HTML yêu cầu máy chủ cho tất cả số vé, sau đó hiển thị chế độ xem "trực tiếp" của tất cả các tệp tải lên đang diễn ra trên máy chủ.

Tôi chưa thể làm việc này vì ngay sau khi bộ điều khiển trả về, Spring gọi cleanupMultipart() trong CommonsMultipartResolver. Vì cờ resolveLazily được đặt thành false, khi cleanupMultipart() được gọi, nó sẽ bắt đầu giải quyết và khởi tạo các tệp nhiều phần. Điều này dẫn đến tình trạng cuộc đua giữa lời gọi đến "request.getFile (" theFile ");" trong runnable và cuộc gọi cleanupMultipart() cuối cùng dẫn đến một ngoại lệ.

Bất kỳ ai có ý tưởng nào? Tôi đang phá vỡ một số loại hợp đồng HTTP ở đây bằng cách muốn làm back-end xử lý tập tin không đồng bộ.

+0

Nhận xét về bài viết của riêng tôi. Tôi tìm thấy các blog sau đây có thể giúp đưa ra một giải pháp. http://blog.springsource.org/2012/05/06/spring-mvc-3-2-preview-introducing-servlet-3-async-support/ https://blogs.oracle.com/ enterprisetechtips/entry/asynchronous_support_in_servlet_3 Tôi sẽ đăng lại nếu tôi đưa ra ví dụ làm việc. – CAL5101

Trả lời

5

Yêu cầu HTTP đã được thực hiện theo chủ đề riêng của nó và khách hàng có thể thực hiện một vài yêu cầu song song, không đồng bộ. Vì vậy, bạn không cần phải bắt đầu một chủ đề mới. Chỉ cần lưu/xử lý tập tin như bình thường, trong chủ đề chính. Chỉ cần thực hiện 'tải lên tệp async' chỉ ở phía khách hàng.

Ngoài ra, bạn chỉ nên gửi phản hồi http khi bạn đã xử lý dữ liệu nhập. Tôi có nghĩa là bạn không thể đọc tiêu đề đầu vào, thực hiện phản hồi http và tiếp tục đọc dữ liệu từ trình duyệt. Tiêu thụ đầu vào -> Xử lý nó -> Gửi đầu ra, cách thức giao thức HTTP 1/1.1 hoạt động.

Nếu bạn cần một số vé để gửi để tải lên, bạn có thể tạo ra nó trước khi tải lên thực tế, bằng cách sử dụng tải lên hai bước, như:

  • Ajax GET yêu cầu để có được số lượng vé
  • POST một nội dung tập tin và số vé (nhận được từ bước trước)
  • + ajax Nhận trạng thái hiện tại cho vé, bất cứ lúc nào sau, async
+0

đồng ý.Tôi chỉ muốn thêm một chút làm rõ: những gì user1404399 được hỏi là làm thế nào để "async tải lên" bởi một chủ đề mới ở phía máy chủ, trong khi đúng cách để xử lý vấn đề này là để làm cho ajax bài bởi javascript để xử lý-tải lên hành động, và báo cáo tiến độ cho người dùng bằng cách bỏ phiếu cho một hành động khác. Đó có phải là ý tưởng của bạn không? –

+0

@ HoàngLong phải –

+0

Cảm ơn các bạn đã trả lời. Tôi đã có một cảm giác tốt rằng điều này là không thể, nhưng tôi đã bị đẩy để tìm một giải pháp. Chúng tôi đã không kết thúc việc thực hiện bất cứ điều gì, nhưng chỉ là một tải lên tập tin bình thường. P.S. Tôi đã cập nhật tên hiển thị của mình thành tên dễ đọc hơn user1404399 – CAL5101

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