2011-11-13 70 views
27

Tôi đã cố gắng xử lý lưu hình ảnh Đã đăng lên nodeJS (và khung công tác nhanh) tới cơ sở dữ liệu và đã gặp một số sự cố. Bỏ qua tất cả quá trình xử lý web, tôi nghĩ rằng tôi đã thu hẹp vấn đề về cách mã hóa base64 đang xảy ra trong nút. Tôi tin rằng ví dụ đơn giản dưới đây sẽ hoạt động, nhưng hình ảnh đầu ra luôn bị hỏng.Mã hóa/giải mã hình ảnh của Baseode 64 không hoạt động được

Ví dụ (1) tải trong một hình ảnh (2) lưu bản sao nếu (image_orig) để xác nhận rằng nút có thể đọc tệp đúng cách. Điều này luôn luôn hoạt động. (3) Tôi lấy hình ảnh và base64 mã hóa nội dung của nó, (4) sau đó giải mã nó. Hình ảnh đầu ra cuối cùng (image_decoded) luôn bị hỏng.

Trợ giúp! (node.js 0.6.0 trên OSX Lion)

console.log("starting"); 
process.chdir(__dirname); 

var fs = require("fs"); 

var image_origial = "image.jpg"; 
fs.readFile(image_origial, function(err, original_data){ 
    fs.writeFile('image_orig.jpg', original_data, function(err) {}); 
    var base64Image = new Buffer(original_data, 'binary').toString('base64'); 
    var decodedImage = new Buffer(base64Image, 'base64').toString('binary'); 
    fs.writeFile('image_decoded.jpg', decodedImage, function(err) {}); 
}); 

Trả lời

95

Tôi nghĩ bạn hiểu nhầm cách sử dụng đối số mã hóa một chút. Nếu bạn định chỉ định mã 'nhị phân', thì bạn cần phải thực hiện nó một cách nhất quán. Nhưng thực sự bạn không cần nó chút nào. Bạn dường như khó hiểu việc sử dụng Buffer vs chuỗi nhị phân.

// This tells node to load the file into a Buffer 'original_data' because you 
// have not specified an encoding for the returned values. If you provided an 
// encoding, then original_data would be a string with that encoding. 
fs.readFile(image_origial, function(err, original_data){ 

    // This tells node to take that buffer, and write it to the new filename. 
    // Again no encoding is provided, so it will assume a Buffer or utf8 string. 
    fs.writeFile('image_orig.jpg', original_data, function(err) {}); 

    // This tells node to create a new buffer from the old buffer, which means 
    // it will iterate over original_data copying the bytes one at a time. But 
    // they will be identical buffers. It will ignore the 'binary' argument 
    // since the object you are passing isn't a string. 
    // Then it encodes the content of that Buffer to base64, which is fine. 
    var base64Image = new Buffer(original_data, 'binary').toString('base64'); 

    // Here you decode the base64 to a buffer, which is fine, but then you 
    // convert the buffer into a string with encoding 'binary'. This means that 
    // it is a string object whose code points are bytes of the buffer. 
    var decodedImage = new Buffer(base64Image, 'base64').toString('binary'); 

    // Here you try to write that String object to a file. Since the argument you 
    // have given is a string and you have not given an encoding argument for the 
    // write command, then it will assume that 'utf8' is the encoding. It will try to 
    // decode your binary string into a utf8 encoded buffer, and write that buffer. 
    // This will cause it to fail because that encoding conversion is wrong. 
    // Really through, 'binary' is just wrong to use. Buffers are already binary. 
    fs.writeFile('image_decoded.jpg', decodedImage, function(err) {}); 
}); 

Ví dụ tiếp theo này sẽ hoạt động nhưng rất không hiệu quả vì thay đổi mã hóa mọi lúc không cần thiết, nhưng tôi chỉ muốn hiển thị nó rõ ràng. Nếu bạn thực sự muốn có một mã hóa cụ thể, bạn cần đảm bảo rằng bạn nhất quán. Mỗi một trong các hàm này đều có đối số mã hóa.

fs.readFile(image_origial, 'binary', function(err, original_data){ 
    fs.writeFile('image_orig.jpg', original_data, 'binary', function(err) {}); 
    var base64Image = new Buffer(original_data, 'binary').toString('base64'); 
    var decodedImage = new Buffer(base64Image, 'base64').toString('binary'); 
    fs.writeFile('image_decoded.jpg', decodedImage, 'binary', function(err) {}); 
}); 

Đây là cách phù hợp để thực hiện. Giữ tất cả mọi thứ dưới dạng Bộ đệm, trừ khi bạn tạo base64.

fs.readFile(image_origial, function(err, original_data){ 
    fs.writeFile('image_orig.jpg', original_data, function(err) {}); 
    var base64Image = original_data.toString('base64'); 
    var decodedImage = new Buffer(base64Image, 'base64'); 
    fs.writeFile('image_decoded.jpg', decodedImage, function(err) {}); 
}); 
+3

Cảm ơn! Điều này giải quyết nó! – Evan

+0

Cảm ơn phản hồi siêu thông tin đó! Tôi cũng có thể mã hóa hình ảnh thành base64 bằng cách sử dụng hướng dẫn của bạn. – zzaman

+1

cách viết 'decodedImage' thành luồng phản hồi? –

11

giải pháp Hơi tốt hơn sẽ là để loại bỏ tất cả các loại kịch câm có thể:

var buff = new Buffer(req.body.imageFile 
    .replace(/^data:image\/(png|gif|jpeg);base64,/,''), 'base64'); 
fs.writeFile('/file/path/', buff, function (err) { 
    console.log('done'); 
}); 

Đây là Ngoài các @ Herve của câu trả lời.

+0

lý do tại sao cần phải loại bỏ các loại mime ?? – user1575921

+2

Dữ liệu meta chỉ được sử dụng trong trình duyệt. Trong trường hợp bạn không gỡ bỏ nó Node lưu trữ hình ảnh bị hỏng. – simo

+0

cảm ơn, tôi hiểu rồi – user1575921

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