2017-05-08 88 views
0

我在做與反應原生的應用程序。現在我試圖從手機發送圖像到服務器(Node Js)。爲此,我使用react-native-image-picker。問題是,當我發送圖像時它保存一個文件,但它是空的不包含照片。我認爲這個問題可能是因爲在不同的設備,服務器無法訪問到圖像的路徑。但我不知道我該怎麼做。將文件發送到節點JS服務器

陣營母語:

openImagePicker(){ 
     const options = { 
     title: 'Select Avatar', 
     storageOptions: { 
      skipBackup: true, 
      path: 'images' 
     } 
     } 

     ImagePicker.showImagePicker(options, (imagen) =>{ 
      if (imagen.didCancel) { 
     console.log('User cancelled image picker'); 
     } 
     else if (imagen.error) { 
     console.log('ImagePicker Error: ', imagen.error); 
     } 
     else if (imagen.customButton) { 
     console.log('User tapped custom button: ', imagen.customButton); 
     } 
     else { 
    let formdata = new FormData(); 
    formdata.append("file[name]", imagen.fileName); 
    formdata.append("file[path]", imagen.path); 
    formdata.append("file[type]", imagen.type); 
      fetch('http://X/user/photo/58e137dd5d45090d0b000006', { 
     method: 'PUT', 
     headers: { 
     'Content-Type': 'multipart/form-data' 
     }, 
     body: formdata 
    }) 
     .then(response => { 
      console.log("ok");  
     }) 
     .catch(function(err) { 
      console.log(err); 
     }) 
    }})} 

節點JS:

addPhotoUser = function (req, res) { 
User.findById(req.params.id, function(err, user) { 
fs.readFile(req.body.file.path, function (err, data) {  
    var pwd = 'home/ubuntu/.../'; 
    var newPath = pwd + req.body.file.name; 
    fs.writeFile(newPath, data, function (err) { 
    imageUrl: URL + req.body.file.name; 
     user.save(function(err) { 
      if(!err) { 
       console.log('Updated'); 
      } else { 
       console.log('ERROR: ' + err); 
      } 
      res.send(user); 
     }); 

    }); 
}); 
}); 
}; 

回答

1

做一個對象,然後發送對象到服務器。該對象將包含名稱,路徑和類型,如下所示:

var imageData = {name: 'image1', path: uri, type: 'image/jpeg'} 

以上是發送圖像數據的一種方法。另一種方法是將其轉換成BLOB使服務器端程序員不必做他們結束這個任務。您可以使用react-native-fetch-blob來製作BLOB。

另一種方式是直接上傳圖片到亞馬遜服務器(S3),併發送鏈接到後端..

函數返回的base64字符串:

var RNFetchBlob = require('react-native-fetch-blob').default; 

getImageAttachment: function(uri_attachment, mimetype_attachment) { 

    return new Promise((RESOLVE, REJECT) => { 

    // Fetch attachment 
    RNFetchBlob.fetch('GET', config.apiRoot+'/app/'+uri_attachment) 
     .then((response) => { 

     let base64Str = response.data; 
     var imageBase64 = 'data:'+mimetype_attachment+';base64,'+base64Str; 
     // Return base64 image 
     RESOLVE(imageBase64) 
    }) 

    }).catch((error) => { 
    // error handling 
    console.log("Error: ", error) 
}); 
}, 

乾杯:)

+0

謝謝!我試着第一個解決方案。我在後臺發送它很好,但在嘗試訪問映像時沒有正確保存並且沒有顯示任何內容。 –

+0

真的發生了什麼? – Codesingh

+0

看到我上面的答案。手機中的uri無法遠程訪問。當他試圖讀取它時,他正試圖讀取uri在手機上的圖像。 – klvs

1

是的,問題是,文件路徑是本地設備,而不是在服務器上。你想發送由react-native-image-picker返回給你的實際數據而不是uri。它看起來像庫的base64所以你會想發送到您的服務器對數據進行編碼,而不是URI從庫返回,因爲它不會是一個遠程服務器上訪問。

這意味着你不會讀取服務器上的任何文件,而只是在響應主體中解碼base64字符串並將其寫入文件系統。

對於客戶端:

let formdata = new FormData(); 
formdata.append("file[name]", imagen.fileName); 
formdata.append("file[data]", imagen.data); // this is base64 encoded! 
formdata.append("file[type]", imagen.type); 
     fetch('http://X/user/photo/58e137dd5d45090d0b000006', { 
    method: 'PUT', 
    headers: { 
    'Content-Type': 'multipart/form-data' 
    }, 
    body: formdata 
}) 

在服務器端atob從的base64解碼之前寫入文件系統:

let decoded = atob(req.body.data) 
// now this is binary and can written to the filesystem 

從那裏:

fs.writeFile(newPath, decoded, function (err) { 
    imageUrl: newPath; 
     user.save(function(err) { 
      if(!err) { 
       console.log('Updated'); 
      } else { 
       console.log('ERROR: ' + err); 
      } 
      res.send(user); 
     }); 

    }); 

注,你不需要你的代碼中的文件系統編寫,因爲你正在解碼那個圖像在您的請求中作爲b64字符串發送。

這似乎也與你如何使用該用戶對象有一些古怪。你似乎只傳遞一個處理錯誤的函數,而不是任何實際的數據。我不知道你在使用什麼ORM,所以很難說它應該如何工作。也許這樣?

user.save({imageUrl:uriReturnedByFsWrite}, (err, data)=>{...}) 

祝你好運:)