0

저는이 문제를 여기에 게시하고 있습니다. 많은 관련 게시물을 읽었지만 그 중 어떤 것도 작동하게 만들었습니다.Mongo의 Gridfs에서 스트리밍 된 이미지가 브라우저에 표시되지 않음

아이디어는 매우 쉽습니다. 이미지를 GridFS에 업로드 할 수있는 MEAN 기반 응용 프로그램이 있습니다. 서버에 로컬로 저장하지 않고 나중에 브라우저에서 시각화 할 수 있습니다.

그럼 시작하겠습니다. AngularJS에서 각 파일 업로드 모듈을 사용하여 이미지를 업로드합니다. 따라서, 내 AngularJS와 컨트롤러 중 하나에 내가 가진 내 노드 + Express 서버에서

$scope.onFileSelect = function(file) { 

    var fileName = file.name; 

    $scope.upload = $upload.upload({ 
     url: '/file/uploadFile', //this is the node route for uploading the file 
     headers: { 
      'fileName':fileName 
     }, 
     file: file 
    }). 
    success(function(data, status, headers, config) { 
    //DOING STUFF 
    }. 
    error(function(data, status, headers, config) { 
    //DOING OTHER STUFF 
    }); 
} 

, 내가 업로드 요청과 그리드 스트림 모듈을 이용하여 이미지를 다운로드 할 수있는 요청을 처리하고 있습니다. 이를 통해 서버에 일시적으로 저장할 필요없이 GridFS에서 이미지를 직접 스트리밍하고 저장할 수 있습니다.

클라이언트 측에
var mongoose = require('mongoose'),Grid = require('gridfs-stream'),gfs; 

mongoose.connection.once('open',function() { 
    gfs = Grid(mongoose.connection.db, mongoose.mongo); 
}); 

exports.uploadFile = function(req, res) { 
    var fileNameHeader = req.headers['filename']; 
    //creating a unique filename 
    var name = uuid.v1(); 
    var extIndex = fileNameHeader.lastIndexOf('.'); 
    var extension = fileNameHeader.substr(extIndex); 
    var fileName = name+extension; 

    var writeStream = gfs.createWriteStream({ 
     filename: fileName, 
     root: 'imagesGrid' 
    }); 
    req.pipe(writeStream); 
    writeStream.on('close',function() { 
     //DOING STUFF 
    }); 
} 

exports.downloadFile = function(req,res) { 
    var name = req.params.name; 
    var readStream = gfs.createReadStream({ 
     filename: name, 
     root: 'imagesGrid' 
    }); 
    res.header({'Content-type': mime.lookup(name)}); 
    readStream.pipe(res); 
}; 

, 나는 모든 HTML 이미지 요소를 생성이 HTML 지시문이 있습니다

내 이미지 - 드래그는 요소 중 하나로서,이
<my-image-draggable ng-repeat="image in userImages"> 
</my-image-draggable> 

:

<img ng-src='{{image.imageId.location}}'> 

런타임시 {{image.imageId.location}}'/file/getFile/2350bcf0-53b4-11e4-9f6b-9fc9a66908c4.jpg'으로 변환되므로 원칙적으로

<img ng-src='/file/getFile/2350bcf0-53b4-11e4-9f6b-9fc9a66908c4.jpg'> 

은 서버에서 downloadFile으로 HTTP GET 요청을 시작해야하며 이미지는 GridFS에서 스트리밍되어 마지막으로 브라우저에 표시되어야합니다. 문제는 이미지가 표시되지 않는다는 것입니다.

가 나는 또한 프로세스를 사전에 시도, 각 컨트롤러에 순서대로 서버에서 전송 된 이미지 데이터베이스 64로 인코딩하고있을 런타임 ng-src에서 같은하자

'data:image/jpeg;base64,'+Base64.encode(data); 

하지만 그것을 둘 다 작동하지 않습니다.

또한 downloadFile 경로를 수동으로 호출하려고 시도했지만 결과가 없습니다. 이것이 작동하지 않는 이유를 알아 내지 못합니다. 이미지가 올바르게 GridFS에 저장되었는지 궁금합니다.

의견이 있으십니까? 같은 문제가 발생한 사람은 누구입니까?

고맙습니다.

+0

문제는 이미지 업로드 때문이다. 서버에있는 파일에서 이미지를 스트리밍하면 모든 것이 잘됩니다. 나는 다른 방법으로 업로드를 시도 할 것이다. – rconfalonieri

+1

나는'socket.io-stream'을 사용하여 Websocket (이미 응용 프로그램을 가지고 있었기 때문에)을 통해 이미지를 스트리밍하기로 바꿨다. ** angular-file-upload **로 파일을 업로드 할 때의 문제는 파일을 멀티 파트로 보내고 있다는 것입니다. 서버 측에서는 파일이 수신되어 DB로 스트리밍 될 때 해당 내용에 정확한 가독성 (클라이언트로 다시 스트리밍 될 때)을 방지하는 추가 정보가 포함되어 있습니다. – rconfalonieri

답변

0

귀하의 socket.io 사용과 같은 결과가 귀하의 문제를 해결 한 것 같지만,이 문제 중 일부를 해결해야만 공유 할 것이라고 생각했습니다.

필자의 경우 이미지 캡션과 같은 이미지에 대한 정보를 저장할 수 있어야합니다. 필자는 사용자가 제공 한 모든 입력 필드와 파일 자체를 포함하는 표준 html 게시 양식을 고수하기로 결정했습니다. 업로드 경로에 대한 미들웨어로 Multer을 사용합니다. 따라서 요청이 내 uploadImg 경로에 도착할 때까지 멀터는 파일뿐만 아니라 양식 필드에 대해서도 구문 분석했습니다.

Multer는 파일을 임시 파일로 저장합니다 (아직 양식 필드를 구문 분석하면서 gridfs-stream으로 스트리밍하는 방법을 찾지 못함). 빠른 해결책은 저장된 임시 파일을 스트리밍 한 다음 완료되면 삭제하는 것입니다. 극도로 확장 가능한 솔루션은 아니지만 현재 우리의 경우에는 충분합니다.

var uploadImg = function(req,res) { 
     var writestream = gfs.createWriteStream({ 
     filename: req.files.file.name, 
     mode:'w', 
     content_type:req.files.file.mimetype, 
     metadata:req.body, 
     }); 
    fs.createReadStream(req.files.file.path).pipe(writestream); 

    writestream.on('close', function (file) { 
     res.send("Success!"); 
     fs.unlink(req.files.file.path, function (err) { 
      if (err) console.error("Error: " + err); 
      console.log('successfully deleted : '+ req.files.file.path); 
     }); 
    }); 

}; 

은 또한이를 참조하십시오 MongoError when uploading a file using mongoose, gridfs-stream and multer

+0

서버에 tmp 파일을 저장할 수 있다면 귀하의 접근 방식은 문제가 없습니다. 그러나 예를 들어 Heroku와 같이 응용 프로그램을 호스팅하기 위해 클라우드 응용 프로그램 플랫폼을 사용하는 경우 (파일을 임시 저장하는 것을 허용하지 않기 때문에) 적합하지 않습니다. 공유 주셔서 감사합니다;) – rconfalonieri

+0

일주일 정도 프로덕션 환경에서 fileupload를 통해 MongoDB에 직접 스트리밍되었습니다. 잘됐다. 관심있는 사람은 [이 답변] (http://stackoverflow.com/a/27163813/3304414)과 [this pull request] (https://github.com/willhuang85/skipper-gridfs/pull/9)를 참조하십시오. – AddieD

관련 문제