2016-05-25 22 views
13

Tôi đang cố triển khai chức năng tải lên tệp trong ứng dụng của mình bằng cách sử dụng Akka HTTP. Tôi đang sử dụng akka-stream phiên bản 2.4.4.Tải lên tệp bằng cách sử dụng Akka HTTP

Đây là mã (sửa đổi từ akka-doc)

path("fileupload") { 
    post { 
     extractRequestContext { 
     ctx => { 
      implicit val materializer = ctx.materializer 
      implicit val ec = ctx.executionContext 
      fileUpload("fileUpload") { 
      case (metadata, byteSource) => 
       val location = FileUtil.getUploadPath(metadata) 
       val updatedFileName = metadata.fileName.replaceAll(" ", "").replaceAll("\"", "") 
       val uniqFileName = uniqueFileId.concat(updatedFileName) 
       val fullPath = location + File.separator + uniqFileName 
       val writer = new FileOutputStream(fullPath) 
       val bufferedWriter = new BufferedOutputStream(writer) 

       val result = byteSource.map(s => { 
       bufferedWriter.write(s.toArray) 
       }).runWith(Sink.ignore) 

       val result1 = byteSource.runWith(Sink.foreach(s=>bufferedWriter.write(s.toArray))) 
       Await.result(result1, 5.seconds) 
       bufferedWriter.flush() 
       bufferedWriter.close() 
       complete(uniqFileName) 
      /*onSuccess(result) { x => 
       bufferedWriter.flush() 
       bufferedWriter.close() 
       complete("hello world") 
      }*/ 
      } 
     } 
     } 
    } 
    } 

Mã này đang làm việc tốt và được tải lên các tập tin vào con đường đã chọn. Tôi đang tạo tên tệp mới bằng cách thêm UUID để đảm bảo rằng tên tệp là duy nhất. Vì vậy, tôi cần phải trả lại tên tập tin mới cho người gọi. Tuy nhiên, phương pháp này không trả lại tên tệp luôn. Đôi khi, nó kết thúc với Response has no content.

Có ai cho tôi biết tôi đang làm gì sai ở đây không?

+1

Đây không phải là câu trả lời cho câu hỏi của bạn, nhưng hãy xem http://doc.akka.io/docs/akka/2.4.6/scala/stream/stages-overview.html#file-io-sinks-and -source thay vì viết bằng tay vào một tập tin. Ngoài ra, bằng cách sử dụng Await.result bên trong một tuyến đường thực sự là phong cách xấu. –

+0

Sẽ xem xét điều đó. Tôi đã thử với onSuccess thay vì Await, bust giống nhau. Vì vậy, tôi đã cố gắng với Await. Cảm ơn bạn đã trả lời, hãy để tôi thử liên kết. –

+0

@ RüdigerKlaehn Tôi đã thử với FileIO, vẫn tồn tại cùng một vấn đề: ( –

Trả lời

14

Không có nhu cầu sử dụng các tiêu chuẩn chặn suối khi bạn có con suối phản ứng cho mục đích đó:

path("fileUpload") { 
    post { 
     fileUpload("fileUpload") { 
     case (fileInfo, fileStream) => 
      val sink = FileIO.toPath(Paths.get("/tmp") resolve fileInfo.fileName) 
      val writeResult = fileStream.runWith(sink) 
      onSuccess(writeResult) { result => 
      result.status match { 
       case Success(_) => complete(s"Successfully written ${result.count} bytes") 
       case Failure(e) => throw e 
      } 
      } 
     } 
    } 
    } 

Mã này sẽ tải lên fileUpload lĩnh vực nhiều phần dữ liệu vào một tập tin bên trong thư mục /tmp. Nó chỉ đổ nội dung của nguồn đầu vào vào tệp chìm tương ứng, trả về một thông báo sau khi hoàn thành thao tác ghi.

Bạn cũng có thể muốn điều chỉnh bộ điều phối được sử dụng cho FileIO nguồn và bồn rửa, như được mô tả trong their scaladocs.

+0

Ngay cả với điều này, tôi không nhận được phản ứng đôi khi: (. Nó cho thấy' Phản ứng là trống rỗng '. Chỉ có sự khác biệt là tôi đang sử dụng 2.4.4 thay vì 2.4.6. –

+0

Làm thế nào để bạn kiểm tra nó? Curl? Đây có phải là một tệp rất lớn không? –

+0

Tôi đang thử nghiệm bằng cách sử dụng phần mở rộng Chome, khách hàng nâng cao, tệp không phải là rất lớn.Thử với tệp txt, sql, jpeg, png min 3kb để tối đa 2 mb –

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