Search code examples
javascriptnode.jsfsyandex-api

Node.js: create a txt file without writing to the device


I have a problem. In my project I get a text and send this text to remote API in .txt file. Now the program does this: getting a text, saving a text in a .txt file in filesystem, uploading a .txt file to remote API. Unfortunately, remote API accepts only files, I can't send plain text in request.

//get the wallPost with the field text
fs.writeFileSync(`./tmp/${wallPostId}.txt`, wallPost.text)

remoteAPI.uploadFileFromStorage(
  `${wallPostPath}/${wallPostId}.txt`,
  `./tmp/${wallPostId}.txt`
)

UPD: In function uploadFileFromStorage, I made a PUT request to remote api with writing a file. Remote API is API of cloud storage which can save only files.

const uploadFileFromStorage = (path, filePath) =>{
let pathEncoded = encodeURIComponent(path)
const requestUrl = `https://cloud-api.yandex.net/v1/disk/resources/upload?&path=%2F${pathEncoded}`
const options = {
  headers: headers
}

axios.get(requestUrl, options)

.then((response) => {
  const uploadUrl = response.data.href
  const headersUpload = {
    'Content-Type': 'text/plain',
    'Accept': 'application/json',
    'Authorization': `${auth_type} ${access_token}`
  }
  const uploadOptions = {
    headers: headersUpload
  }
  axios.put(
    uploadUrl,
    fs.createReadStream(filePath),
    uploadOptions
  ).then(response =>
    console.log('uploadingFile: data  '+response.status+" "+response.statusText)
  ).catch((error) =>
    console.log('error uploadFileFromStorage '+ +error.status+" "+error.statusText)
  )
})

But i guess in the future such a process will be slow. I want to create and upload a .txt file in RAM memory (without writing on drive). Thanks for your time.


Solution

  • You're using the Yandex Disk API, which expects files because that's what it's for: it explicitly stores files on a remote disk.

    So, if you look at that code, the part that supplies the file content is supplied via fs.createReadStream(filePath), which is a Stream. The function doesn't care what builds that stream, it just cares that it is a stream, so build your own from your in-memory data:

    const { Readable } = require("stream");
    
    ...
    
    const streamContent = [wallPost.text];
    const pretendFileStream = Readable.from(streamContent);
    
    ...
    
    axios.put(
      uploadUrl,
      pretendFileStream,
      uploadOptions
    ).then(response =>
      console.log('uploadingFile: data  '+response.status+" "+response.statusText)
    )
    

    Although I don't see anything in your code that tells the Yandex Disk API what the filename is supposed to be, but I'm sure that's just because you edited the post for brevity.