2015-04-10 15 views
17

Tôi đang làm việc trên meanjs ứng dụng được tạo bằng cách sử dụng https://github.com/DaftMonk/generator-angular-fullstack. Tôi đang cố gắng tạo tệp .pdf bằng cách sử dụng phantomjs và tải xuống trình duyệt.Tệp .pdf đã tải xuống bị hỏng khi sử dụng expressjs

Vấn đề là tệp .pdf đã tải xuống luôn hiển thị các trang trống bất kể số trang. Tệp gốc trên máy chủ không bị hỏng. Khi tôi điều tra thêm, thấy rằng tệp đã tải xuống luôn lớn hơn nhiều so với tệp gốc trên đĩa. Vấn đề này cũng chỉ xảy ra với tệp .pdf. Các loại tệp khác đang hoạt động tốt.

Tôi đã thử một số phương pháp như res.redirect('http://localhost:9000/assets/exports/receipt.pdf');, res.download('client\\assets\\exports\\receipt.pdf'),

var fileSystem = require('fs'); 
var stat = fileSystem.statSync('client\\assets\\exports\\receipt.pdf'); 
res.writeHead(200, { 
        'Content-Type': 'application/pdf', 
        'Content-Length': stat.size 
       }); 

var readStream = fileSystem.createReadStream('client\\assets\\exports\\receipt.pdf'); 
return readStream.pipe(res); 

và thậm chí tôi đã cố gắng với https://github.com/expressjs/serve-static không có thay đổi trong kết quả.

Tôi mới đến nodejs. Cách tốt nhất để tải xuống tệp .pdf xuống trình duyệt là gì?

Cập nhật: Tôi đang chạy này trên Windows 8.1 64bit Computer

+0

Tôi gặp sự cố tương tự khi làm việc với ngăn xếp microsoft và AngularJS SPA. Khi tiêu đề đã chính xác, tệp đã được phục vụ đúng cách cho ứng dụng khách, nhưng blob của ứng dụng khách đã không lưu ngay cho đến khi tôi sử dụng filesaver.js. –

+0

Cùng một vấn đề ở đây. Điều này có được giải quyết không ?? – Chinni

Trả lời

3

Thông thường nếu bạn đang sử dụng ma để tạo ra một pdf sau đó file sẽ được ghi vào đĩa và bạn phải cung cấp đường dẫn và một gọi lại hàm render.

router.get('/pdf', function(req, res){ 
    // phantom initialization and generation logic 
    // supposing you have the generation code above 
    page.render(filePath, function (err) { 
     var filename = 'myFile.pdf'; 
     res.setHeader('Content-type', "application/pdf"); 
     fs.readFile(filePath, function (err, data) { 
      // if the file was readed to buffer without errors you can delete it to save space 
      if (err) throw err; 
      fs.unlink(filePath); 

      // send the file contents 
      res.send(data); 
     }); 
    }); 
}); 
+0

Tôi đã thử phương pháp này và giống như tất cả các phương thức trước đó, tệp đã tải xuống lớn hơn (25 KB) và tệp được tạo trên máy chủ là 16 KB. –

+0

tôi đã có cùng một vấn đề, trên localhost, nhưng sau đó tôi triển khai trên heroku và tất cả mọi thứ hoạt động trơn tru. Nhưng thật đáng buồn là tôi không có lời giải thích. – AndreiC

4

Dưới đây là một cách sạch để phục vụ cho một tập tin từ nhanh, và sử dụng một tiêu đề attachment để đảm bảo các tập tin được tải về:

var path = require('path'); 
var mime = require('mime'); 

app.get('/download', function(req, res){ 
    //Here do whatever you need to get your file 
    var filename = path.basename(file); 
    var mimetype = mime.lookup(file); 

    res.setHeader('Content-disposition', 'attachment; filename=' + filename); 
    res.setHeader('Content-type', mimetype); 

    var filestream = fs.createReadStream(file); 
    filestream.pipe(res); 
}); 
+1

Tôi cũng đã thử phương pháp này và giống như tất cả các phương pháp trước đó, tệp đã tải xuống lớn hơn (25 KB) và tệp được tạo trên máy chủ là 16 KB. –

3

Có một vài cách để làm điều này :

  1. Nếu tệp là tài liệu tĩnh như tài liệu, readme, v.v, bạn có thể cho biết rằng thư mục của tôi có tệp tĩnh (và có sẵn trực tiếp) và giữ tập tin ở đó. Điều này được thực hiện bằng cách sử dụng phần mềm trung gian tĩnh: app.use (express.static (pathtofile)); Dưới đây là liên kết: http://expressjs.com/starter/static-files.html

Bây giờ bạn có thể trực tiếp mở file bằng cách sử dụng url từ trình duyệt như:

window.open('http://localhost:9000/assets/exports/receipt.pdf'); 

hoặc

res.redirect('http://localhost:9000/assets/exports/receipt.pdf'); 

nên làm việc.

  1. Cách thứ hai là đọc tệp, dữ liệu phải đến dưới dạng bộ đệm. Trên thực tế, nó phải được nhận ra nếu bạn gửi trực tiếp, nhưng bạn có thể thử chuyển đổi nó sang mã hóa base64 bằng cách sử dụng:

    var base64String = buf.toString ('base64');

sau đó thiết lập các kiểu nội dung:

res.writeHead(200, { 
        'Content-Type': 'application/pdf', 
        'Content-Length': stat.size 
       }); 

và gửi dữ liệu như phản ứng. Tôi sẽ cố gắng đưa ra một ví dụ về điều này.

EDIT: Bạn thậm chí không cần mã hóa nó. Bạn có thể thử điều đó. Nhưng tôi đã có thể làm cho nó hoạt động mà không cần mã hóa nó.

Ngoài ra, bạn cũng không cần đặt tiêu đề. Express làm điều đó cho bạn. Sau đây là đoạn mã Snippet của API được viết để lấy pdf trong trường hợp nó không được công khai/tĩnh. Bạn cần API để phân phối pdf:

router.get('/viz.pdf', function(req, res){ 
    require('fs').readFile('viz.pdf', function(err, data){ 
     res.send(data); 
    }) 
}); 

Cuối cùng, lưu ý rằng url để nhận pdf có phần mở rộng là pdf, đây là trình duyệt để nhận dạng tệp đến là pdf. Nếu không, nó sẽ lưu tệp mà không có bất kỳ phần mở rộng nào.

0

Tôi không có kinh nghiệm về các khuôn khổ mà bạn đã đề cập nhưng tôi khuyên bạn nên sử dụng một công cụ như Fiddler để xem những gì đang diễn ra. Ví dụ: bạn có thể không cần phải thêm tiêu đề nội dung độ dài vì bạn đang phát trực tiếp và khung của bạn không mã hóa chuyển mã hóa, v.v.

4

Tôi đã tham nhũng khi cung cấp tệp pdf tĩnh. Tôi đã thử mọi thứ được đề xuất ở trên. Sau đó, tôi đã tìm thấy điều này: https://github.com/intesso/connect-livereload/issues/39 Về bản chất, kết nối gan thông thường xuất sắc (gói ~ 0.4.0) đã làm hỏng bản pdf. Vì vậy, chỉ làm cho nó bỏ qua file PDF qua:

app.use(require('connect-livereload')({ignore: ['.pdf']})); 

hiện đang làm việc này:

app.use('/pdf', express.static(path.join(config.root, 'content/files'))); 

... cứu trợ tuyệt vời.

+1

Tôi ước tôi có thể truyền nhiều hơn một bài viết. Tôi đã gặp vấn đề này trong hơn 5 tháng và sử dụng cách khắc phục/nhận xét của bạn về cấu hình kết nối-ganeload đã khiến vấn đề biến mất. –

+0

Tôi bị cám dỗ để tạo tài khoản stackoverflow mới chỉ để upvote này. Tôi đã tìm thấy nhiều giải pháp tại SO, nhưng sự kỳ quặc của điều này thực sự đã lấy bánh. Tôi nghĩ rằng đó là một số nén flakey, nhưng không bao giờ có thể đoán kết nối-ganeload đã rối tung với nó. Nó đã xảy ra với tôi với các tệp .zip ... Yikes! CẢM ƠN BẠN! – treejanitor

+0

Cảm ơn bạn SO MUCH! Tôi và đồng nghiệp của tôi đã dành cả ngày để tìm ra những gì đang xảy ra. – Kreozot

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