2010-07-28 30 views
11

Greetings,Triggering một download file mà không cần bất kỳ yêu cầu máy chủ

Tôi đang làm việc trên một ứng dụng JS dựa trên hiện một số công việc phức tạp và ghi lại một số thông tin (trên thực tế, lên đến hàng trăm dòng) trên <div>.

Mục tiêu của tôi là có nút "Lưu nhật ký" kích hoạt hộp thoại tải xuống của trình duyệt để lưu nội dung ghi nhật ký của tôi <div>.

chính xác hơn, đó là những yêu cầu về tính năng này:

  • Người dùng cuối cùng phải có toàn quyền kiểm soát các tập tin. S/anh ta có thể lưu/lưu trữ nó để tham khảo trong tương lai, gửi nó tới bộ phận hỗ trợ để được trợ giúp giải quyết một số vấn đề, tải nó trở lại ứng dụng, v.v. Vậy API lưu trữ web của HTML5 không giúp ích gì (dữ liệu sẽ được lưu vào một vị trí do trình duyệt xác định và sẽ không thể dễ dàng truy xuất được ngoại trừ từ JS tạo ra nó).
  • Ứng dụng phải có khả năng hoạt động ngoại tuyến (ít nhất trong một số trường hợp). Đó là, và hiệu quả, là lý do tại sao tôi loại bỏ ý tưởng POST dữ liệu đến máy chủ để lấy lại nó với tiêu đề "Bố cục nội dung".
  • Tệp phải được đánh dấu đúng là text/plain, do đó trình duyệt có thể đề xuất các tác vụ mặc định (như "Mở trên notepad") giống như khi tải xuống tệp thông thường. Điều này có thể được xem như là một khía cạnh cụ thể của yêu cầu đầu tiên.
  • Nói cho người dùng sao chép và dán nội dung của <div> vào trình chỉnh sửa văn bản và lưu nó từ đó chắc chắn là khủng khiếp và chính xác là lý do tôi đang cố tránh.

Tôi đã tìm kiếm trên trang web này, trên các trang web WHATWG và W3C và trên web nói chung không thành công. Liệu điều này có thể làm được không?

Gần nhất tôi có được là sử dụng địa chỉ data:. Nỗ lực đầu tiên của tôi, thực hiện một hành động POST, không thể có được một loại nội dung thông qua, do đó, nó sẽ trở lại với các chẩn đoán của UA. Tôi đã nhận được nó tốt hơn một chút bằng cách tạo một liên kết <a> trông giống như một nút và gán cho nó thuộc tính type, nhưng sau đó UA sẽ phát quá thông minh và hiển thị nội dung thay vì lưu (và yêu cầu người dùng lưu tệp từ trình duyệt tại bước đó thậm chí còn tồi tệ hơn so với cách tiếp cận sao chép-dán, vì tiết kiệm trang thay đổi rất nhiều giữa các trình duyệt).

Nếu chỉ có một số cách để kết hợp một URL data: với gợi ý giống như "bố cục nội dung", mọi thứ có thể thực sự suôn sẻ.

Kính trọng, Herenvardo

+1

Có đang sử dụng một plugin như Flash không? Tôi không biết liệu nó có thể làm với HTML tiêu chuẩn, nhưng nó sẽ là khá dễ dàng nếu Flash là một lựa chọn ... –

+0

Tôi đã có một câu hỏi tương tự http://stackoverflow.com/questions/2832392/can-you- do-file-io-using-javascript-without-activex nhưng chỉ có một câu trả lời. Tôi không nghĩ rằng nó là có thể mặc dù. –

+0

Có phải "sao chép vào clipboard với mã và yêu cầu người dùng dán nó vào notepad (hoặc trình soạn thảo văn bản yêu thích)" ý tưởng xuất hiện không? Clipboard có thể xử lý megabyte, notepad có thể bị nghẹt thở trên một vài megabyte mặc dù. Mặt khác: xem http://stackoverflow.com/questions/17836273/export-javascript-data-to-csv-file-without-server-interaction – TWiStErRob

Trả lời

2

Thật không may đây không phải là một cái gì đó bạn có thể làm với khả năng trình duyệt bình thường. Một cái gì đó giống như flash hoặc plugin dành riêng cho trình duyệt sẽ giúp bạn có được những gì bạn cần, nhưng giới hạn bảo mật trong javascript sẽ không cho phép bạn tải xuống dữ liệu tùy ý được tạo trong trình duyệt.

Ngoài ra, url 'dữ liệu' không được hỗ trợ trên tất cả các kết hợp trình duyệt/phiên bản. Tôi không chắc liệu người dùng của bạn có bị ràng buộc với trình duyệt nào họ đang sử dụng hay không nhưng điều đó có thể hạn chế những gì bạn có thể làm với giải pháp đó.

+0

Cảm ơn! Dường như phương pháp tiếp cận dựa trên trình cắm thêm (hoặc Flash) là cách duy nhất mà tất cả các yêu cầu có thể được đáp ứng. Một lưu ý phụ, hỗ trợ cho 'dữ liệu:' không phải là vấn đề: ứng dụng nói chung dựa trên rất nhiều tính năng HTML5, vì vậy đã có yêu cầu trình duyệt nặng, yêu cầu hỗ trợ cho 'data:' won ' Đó là một vấn đề lớn. –

+1

Ngoài ra, Silverlight có thể là một lựa chọn khả thi ở đây. –

2

Giải pháp này hơi phức tạp nhưng sẽ phù hợp với nhu cầu của bạn, có lẽ đó là một lựa chọn.

Tạo máy chủ web tùy chỉnh chỉ trả về nội dung của bất kỳ GET hoặc POST dưới dạng văn bản/đồng bằng.

Lưu trữ máy chủ web đó trên cùng một hộp với ứng dụng web nhưng chạy trên một cổng khác. Khi bạn nhấp vào nút Lưu nhật ký, yêu cầu sẽ được gửi đến máy chủ tùy chỉnh và tệp văn bản được trả về.

Dưới đây là một bằng chứng của khái niệm máy chủ trong Java mà sẽ làm việc đó:

// After running this program, access with your browser at 127.0.0.1:8080 

import java.net.*; 
import java.io.*; 

public class ReturnTextFile 
{ 

    public static void main(String[] args) 
    { 

    try 
    { 
     ServerSocket server = new ServerSocket(8080); 
     Socket connection = null; 

     while (true) 
     { 

     try 
     { 
      connection = server.accept(); 

      BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); 

      String input = in.readLine(); 

      // TODO: Clean up input 

      Writer out = new OutputStreamWriter(connection.getOutputStream()); 

      String output = "HTTP/1.1 200 OK\n" + 
        "Connection: close\n" + 
        "Content-Disposition: attachment; filename=log.txt\n" + 
        "Content-Type: text/plain; charset=utf-8\n" + 
        "\n"; 

      output += input; 

      out.write(output); 

      out.flush(); 

      connection.close(); 
     } 
     catch (IOException ex) 
     { 
      ex.printStackTrace(); 
     } 
     finally 
     { 
      if (connection != null) 
      { 
      connection.close(); 
      } 
     } 

     } 

    } 
    catch (IOException ex) 
    { 
     ex.printStackTrace(); 
    } 

    } 
} 
+0

+1 cho cách tiếp cận thú vị như vậy. Tôi chắc chắn sẽ giữ ý tưởng của một máy chủ địa phương trong tâm trí cho các dự án trong tương lai, nhưng câu trả lời của Mike dường như giải quyết vấn đề dễ dàng hơn nhiều. –

2

Bạn có thể thiết lập các content-type trong URL data:, Một cái gì đó như thế này:

data:text/plain,this is some text 

Tuy nhiên, mà vẫn có vấn đề của trình duyệt sẽ tự động hiển thị nó dưới dạng văn bản. Bạn thực sự có hai lựa chọn mà tôi có thể nhìn thấy. Một là bạn đặt loại cho một loại kiểu nhị phân nào đó để trình duyệt không thử và hiển thị nó hoặc bạn có kiểu như văn bản/đồng bằng và giúp người dùng nhấp chuột phải và lưu dưới dạng. Có lẽ một cái gì đó here có thể giúp đỡ?

1

Tôi đã đi xuống con đường này và tôi cũng muốn làm điều đó hoàn toàn ở phía khách hàng. Nhưng nó rất khả thi. Cách duy nhất bạn có thể kích hoạt hộp thoại lưu mà không có bất kỳ phiền toái nào là thực hiện yêu cầu HTTP POST và máy chủ phản hồi với tiêu đề content-disposition.

Tôi có chức năng mong muốn của bạn trong các đoạn mã trên my dusty old blog. Tôi có một biểu mẫu với một trường ẩn được trỏ tới trình xử lý HTTP tùy chỉnh. Javascript lấy văn bản bên trong của khối mã, đặt nó vào trường ẩn và gửi biểu mẫu. Máy chủ phản hồi với toàn bộ phần thân yêu cầu, cùng với các tiêu đề bắt buộc. Không làm mới, bạn nhấp vào nó và bạn nhận được một hộp thoại lưu. Hoạt động tuyệt vời!

+0

Điều gì về việc sử dụng tiêu đề 'http-equiv' trong giao lộ với một' dữ liệu: 'URI để mô phỏng đầu trang? Liệu điều đó có hiệu quả? – haxxerz

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