2008-09-29 33 views
40

Ứng dụng của tôi tạo tệp PDF để sử dụng cho người dùng. Tiêu đề http "Bố cục nội dung" được đặt như đã đề cập here. Điều này được đặt thành "inline; filename = foo.pdf", đủ để Acrobat cung cấp "foo.pdf" làm tên tệp khi lưu pdf."tên" web pdf để lưu mặc định tốt hơn tên tệp trong Acrobat?

Tuy nhiên, khi nhấp vào nút "Lưu" trong Acrobat được nhúng trình duyệt, tên mặc định để lưu không phải là tên tệp mà thay vào đó URL có dấu gạch chéo được thay đổi thành gạch dưới. Rất lớn và xấu xí. Có cách nào để ảnh hưởng đến tên tệp mặc định này trong Adobe không?

Có chuỗi truy vấn trong URL và điều này không thể thương lượng được. Điều này có thể đáng kể, nhưng việc thêm "& foo =/title.pdf" vào cuối URL không ảnh hưởng đến tên tệp mặc định.

Cập nhật 2: Tôi đã thử cả

content-disposition inline; filename=foo.pdf 
Content-Type   application/pdf; filename=foo.pdf 

content-disposition inline; filename=foo.pdf 
Content-Type   application/pdf; name=foo.pdf 

(như xác minh thông qua Firebug) Đáng buồn thay, không phải làm việc.

Một url mẫu là

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true

mà dịch để mặc định Acrobat tiết kiệm như tên tập tin của

http___localhost_bar_sessions_958d8a22-0_views_1493881172_export_format=application_pdf&no-attachment=true.pdf

Cập nhật 3: Julian Reschke mang lại cái nhìn sâu sắc thực tế và sự chặt chẽ cho trường hợp này. Xin vui lòng upvote câu trả lời của mình. Điều này dường như bị hỏng trong FF (https://bugzilla.mozilla.org/show_bug.cgi?id=433613) và IE nhưng hoạt động trong Opera, Safari và Chrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf

Trả lời

10

Một phần của sự cố là RFC 2183 có liên quan không thực sự nêu rõ phải làm gì với loại bố cục "nội tuyến" và tên tệp.

Ngoài ra, theo như tôi có thể nói, UA duy nhất thực sự sử dụng tên tệp cho type = inline là Firefox (xem test case).

Cuối cùng, không rõ ràng API plugin thực sự làm cho thông tin đó có sẵn (có thể người quen quen với API có thể xây dựng).

Điều đó đang được nói, tôi đã gửi một con trỏ tới câu hỏi này cho một người Adobe; có lẽ đúng người sẽ có một cái nhìn.

Có liên quan: xem cố gắng làm rõ Bố cục nội dung trong HTTP ở draft-reschke-rfc2183-in-http - đây là công việc ban đầu đang được tiến hành, phản hồi được đánh giá cao.

Cập nhật: Tôi đã thêm test case, điều này dường như chỉ ra rằng plugin trình đọc Acrobat không sử dụng tiêu đề phản hồi (trong Firefox), mặc dù API plugin cung cấp quyền truy cập vào chúng.

+1

Có giải pháp/công việc xung quanh vấn đề này không? –

+0

Tôi vừa cố thêm nội dung bố trí nội tuyến; filename = foo.pdf và dường như hoạt động trong Chrome, ít nhất. – gorantq

0

Bạn luôn có thể có hai liên kết. Một mở tài liệu bên trong trình duyệt và một tài liệu khác để tải xuống (sử dụng loại nội dung không chính xác). Đây là những gì Gmail làm.

+0

Xin lỗi, nhưng tôi tin rằng điều này sẽ tồi tệ hơn (liên quan đến trải nghiệm người dùng) hơn là không làm gì cả. Đổi tên một tập tin không phải là một vấn đề lớn, chỉ là một vấn đề khó chịu. –

+0

Đủ công bằng. Gmail thực hiện điều này với hình ảnh và tôi rất thích cá nhân. Chúc may mắn anyway :-) –

7

Đặt tên tệp trong ContentType. Điều này sẽ giải quyết vấn đề.

context.Response.ContentType = "application/pdf; name=" + fileName; 
// the usual stuff 
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName); 

Sau khi bạn đặt tiêu đề bố cục nội dung, cũng thêm tiêu đề nội dung độ dài, sau đó sử dụng binarywrite để truyền tệp PDF.

context.Response.AddHeader("Content-Length", fileBytes.Length.ToString()); 
context.Response.BinaryWrite(fileBytes); 
+1

Anh ấy đã làm điều đó. Acrobat Reader bỏ qua nó, hoặc có vẻ như vậy. –

+1

Gợi ý là đặt ContentType = "application/pdf; name = foo.pdf" mà anh ấy không nói là anh ấy đã thử. – Vivek

+0

Tôi đã hy vọng cao, nhưng điều này dường như không ảnh hưởng đến Acrobat Reader 8.0 trong IE hoặc FF. Đã cập nhật câu hỏi. –

1

Thay vì tập tin đính kèm bạn có thể thử inline:

Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf"); 

tôi đã sử dụng nội tuyến trong một ứng dụng web trước đó tạo ra Crystal Reports vào PDF và gửi rằng trong trình duyệt cho người dùng.

9

Giống như bạn, tôi đã cố gắng và cố gắng làm cho công việc này hoạt động. Cuối cùng tôi đã từ bỏ ý tưởng này và chỉ chọn cách giải quyết.

Tôi đang sử dụng ASP.NET MVC Framework, vì vậy tôi đã sửa đổi tuyến đường cho bộ điều khiển/hành động đó để đảm bảo rằng tệp PDF được phân phát là phần cuối cùng của phần vị trí của URI (trước chuỗi truy vấn) và chuyển mọi thứ khác trong chuỗi truy vấn.

Ví dụ:

Cũ URI:

http://server/app/report/showpdf?param1=foo&param2=bar&filename=myreport.pdf

New URI:

http://server/app/report/showpdf/myreport.pdf?param1=foo&param2=bar

Tiêu đề kết quả trông giống hệt như những gì bạn đã mô tả (content-type là ứng dụng/pdf, bố cục nội tuyến, tên tệp là phần vô dụng của tiêu đề). Acrobat hiển thị nó trong cửa sổ trình duyệt (không lưu dưới dạng hộp thoại) và tên tệp được tự động điền nếu người dùng nhấp vào nút Lưu Acrobat là tên tệp báo cáo.

Một vài lưu ý:

Để cho tên tập tin để tìm đàng hoàng, họ không nên có bất kỳ thoát ký tự (ví dụ, không có không gian, vv) ... mà là một chút hạn chế. Tên tệp của tôi được tạo tự động trong trường hợp này và trước đó có khoảng trống trong chúng, được hiển thị dưới dạng '% 20' trong tên tệp hộp thoại lưu kết quả. Tôi chỉ thay thế các dấu cách bằng dấu gạch dưới, và nó đã được giải quyết.

Đây không phải là giải pháp tốt nhất, nhưng nó hoạt động. Nó cũng có nghĩa là bạn phải có tên tệp sẵn có để biến nó thành một phần của URI gốc, điều này có thể gây rối với luồng công việc của chương trình của bạn. Nếu nó hiện đang được tạo hoặc truy xuất từ ​​cơ sở dữ liệu trong suốt cuộc gọi phía máy chủ tạo PDF, bạn có thể cần phải di chuyển mã tạo tên tệp thành javascript như một phần của gửi biểu mẫu hoặc nếu nó đến từ cơ sở dữ liệu, hãy gọi nhanh ajax để lấy tên tệp khi tạo URL dẫn đến PDF nội tuyến.

Nếu bạn đang lấy tên tệp từ đầu vào của người dùng trên biểu mẫu, khi đó cần được xác thực không chứa các ký tự thoát, điều này sẽ làm người dùng khó chịu.

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

+0

Ý tưởng tuyệt vời. :) –

0

Tôi đã được chuyển hướng đến đây vì tôi có cùng sự cố. Tôi cũng đã thử cách giải quyết của Troy Howard nhưng nó dường như không hoạt động.

Cách tiếp cận tôi đã thực hiện đối với điều này là KHÔNG CÒN sử dụng đối tượng phản hồi để ghi tệp khi đang di chuyển. Vì PDF đã có sẵn trên máy chủ, điều tôi đã làm là chuyển hướng trang của tôi trỏ đến tệp PDF đó. Hoạt động tuyệt vời.

http://forums.asp.net/t/143631.aspx

Tôi hy vọng lời giải thích mơ hồ của tôi đã cho bạn một ý tưởng.

-1

Hãy thử điều này, nếu thực thi của bạn là "get.cgi"

http://server,org/get.cgi/filename.pdf?file=filename.pdf

Vâng, nó hoàn toàn mất trí. Không có tệp nào được gọi là "filename.pdf" trên máy chủ, có thư mục ở tất cả dưới tệp get.cgi thực thi.

Nhưng có vẻ như nó hoạt động. Máy chủ bỏ qua filename.pdf và người đọc pdf bỏ qua "get.cgi"

Dan

+0

Điều đó dường như dựa vào một lỗi trong máy chủ web của bạn? Đó là 404 theo spec - hiện Apache cư xử theo cách này? –

+0

Đó không phải là * hoàn toàn * điên rồ, cũng không nhất thiết phải dẫn đến 404. Các đường dẫn bổ sung sau tệp thực thi CGI là hợp lệ và sẽ dẫn đến biến CGI PATH_INFO được đặt. Điều đó nói rằng, tôi không nghĩ đó là cách sạch nhất để giải quyết vấn đề này. – asmecher

1

Tôi tin rằng điều này đã được đề cập trong một hương vị này hay cách khác nhưng tôi sẽ cố gắng và nêu nó trong riêng tôi từ ngữ.

Thay vì điều này:

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true 

tôi sử dụng này:

/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf?GeneratePDF=1 

Thay vì phải "xuất khẩu" quá trình theo yêu cầu, khi có một request đến, tôi nhìn vào URL cho GeneratePDF = 1. Nếu tìm thấy, tôi chạy bất kỳ mã nào đang chạy trong "xuất" thay vì cho phép hệ thống của tôi tìm cách và phân phát tệp PDF ở vị trí /bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf. Nếu GeneratePDF không được tìm thấy trong URL, tôi chỉ cần truyền tải tệp được yêu cầu. (lưu ý rằng tôi không thể chuyển hướng đến tệp được yêu cầu - hoặc nếu không tôi sẽ kết thúc theo vòng lặp vô tận)

2

Nếu bạn sử dụng asp.net, bạn có thể kiểm soát tên tệp pdf thông qua tên tệp trang (url). Khi người dùng khác đã viết, Acrobat là một chút ... khi nó chọn tên tệp pdf khi bạn nhấn nút "lưu": nó lấy tên trang, loại bỏ phần mở rộng và thêm ".pdf". Vì vậy, /foo/bar/GetMyPdf.aspx cung cấp cho GetMyPdf.pdf.

Giải pháp duy nhất tôi thấy là để quản lý tên trang "năng động" thông qua phương thức thụ lý asp.net:

  • tạo ra một lớp mà thực hiện IHttpHandler
  • bản đồ một handler trong web.cấu hình bao bọc với lớp

Mapping1: tất cả các trang có một cơ số chung (MyDocument_):

<httpHandlers> 
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/> 

Mapping2: tên tập tin hoàn toàn miễn phí (cần một thư mục trong đường dẫn):

<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/> 

Một số mẹo ở đây (bản pdf được tạo động bằng iTextSharp):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html

0

Cách tôi giải quyết vấn đề này (với PHP) như sau:

Giả sử URL của bạn là SomeScript.php?id=ID&data=DATA và tệp bạn muốn sử dụng là TEST.pdf.

Thay đổi URL thành SomeScript.php/id/ID/data/DATA/EXT/TEST.pdf.

Điều quan trọng là tham số cuối cùng là tên tệp bạn muốn Adobe sử dụng ('EXT' có thể là bất kỳ thứ gì). Đảm bảo không có ký tự đặc biệt trong chuỗi ở trên, BTW.

Bây giờ, ở phía trên cùng của SomeScript.php, thêm:

$_REQUEST = MakeFriendlyURI($_SERVER['PHP\_SELF'], $_SERVER['SCRIPT_FILENAME']); 

Sau đó, thêm chức năng này để SomeScript.php (hoặc thư viện chức năng của bạn):

function MakeFriendlyURI($URI, $ScriptName) { 

/* Need to remove everything up to the script name */ 
$MyName = '/^.*'.preg_quote(basename($ScriptName)."/", '/').'/'; 
$Str = preg_replace($MyName,'',$URI); 
$RequestArray = array(); 

/* Breaks down like this 
     0  1  2  3  4  5 
    PARAM1/VAL1/PARAM2/VAL2/PARAM3/VAL3 
*/ 

$tmp = explode('/',$Str); 
/* Ok so build an associative array with Key->value 
    This way it can be returned back to $_REQUEST or $_GET 
*/ 
for ($i=0;$i < count($tmp); $i = $i+2){ 
    $RequestArray[$tmp[$i]] = $tmp[$i+1]; 
} 
return $RequestArray;  
}//EO MakeFriendlyURI 

Bây giờ $_REQUEST (hoặc $_GET nếu bạn thích) được truy cập như bình thường $_REQUEST['id'], $_REQUEST['data'], v.v.

Và Ado sẽ sử dụng tên tệp mong muốn của bạn làm mặc định lưu dưới dạng hoặc thông tin email khi bạn gửi nội tuyến.

0

Đối với bất kỳ ai vẫn nhìn vào điều này, tôi đã sử dụng giải pháp được tìm thấy here và nó hoạt động tuyệt vời. Cảm ơn Fabrizio!

+0

Được giảm giá vì chỉ liên kết. –

1

thoại File download (PDF) với lưu và tùy chọn mở

điểm cần nhớ:

  1. Return Stream với kích thước mảng đúng từ dịch vụ
  2. Đọc arrary byte từ dòng với chiều dài byte đúng trên cơ sở chiều dài luồng.
  3. bộ đúng contentType

Đây là mã cho dòng đọc và mở hộp thoại File download cho file PDF

private void DownloadSharePointDocument() 
{ 
    Uri uriAddress = new Uri("http://hyddlf5187:900/SharePointDownloadService/FulfillmentDownload.svc/GetDocumentByID/1/drmfree/"); 
    HttpWebRequest req = WebRequest.Create(uriAddress) as HttpWebRequest; 
    // Get response 
    using (HttpWebResponse httpWebResponse = req.GetResponse() as HttpWebResponse) 
    { 
     Stream stream = httpWebResponse.GetResponseStream(); 
     int byteCount = Convert.ToInt32(httpWebResponse.ContentLength); 
     byte[] Buffer1 = new byte[byteCount]; 
     using (BinaryReader reader = new BinaryReader(stream)) 
     { 
      Buffer1 = reader.ReadBytes(byteCount); 
     } 
     Response.Clear(); 
     Response.ClearHeaders(); 
     // set the content type to PDF 
     Response.ContentType = "application/pdf"; 
     Response.AddHeader("Content-Disposition", "attachment;filename=Filename.pdf"); 
     Response.Buffer = true; 
     Response.BinaryWrite(Buffer1); 
     Response.Flush(); 
     // Response.End(); 
    } 
} 
4

Trong 2.0 thay đổi ASP.NET URL từ

http://www. server.com/DocServe.aspx?DocId=XXXXXXX 

đến

http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX 

Tính năng này hoạt động với Acrobat 8 ​​và tên tệp SaveAs mặc định hiện là MySaveAsFileName.pdf.

Tuy nhiên, bạn phải hạn chế các ký tự được phép trong MySaveAsFileName (không có dấu chấm, v.v ...).

4

Apache's mod_rewrite có thể giải quyết vấn đề này.

Tôi có dịch vụ web có điểm cuối tại /foo/getDoc.service. Tất nhiên Acrobat sẽ lưu các tập tin như getDoc.pdf. Tôi thêm vào các dòng sau trong apache.conf:

LoadModule  RewriteModule   modules/mod_rewrite.so 
RewriteEngine on 
RewriteRule ^/foo/getDoc/(.*)$ /foo/getDoc.service  [P,NE] 

Bây giờ khi tôi yêu cầu /foo/getDoc/filename.pdf?bar&qux, nó được viết lại để nội /foo/getDoc.service?bar&qux, vì vậy tôi nhấn endpoint chính xác của các dịch vụ web, nhưng Acrobat nghĩ rằng nó sẽ lưu tập tin của tôi như filename.pdf.

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