kakadais
kakadais

Reputation: 491

Create ReadStream from Base64 encoded string by file

I feel I got lack of understanding about Buffer and File Stream, but I can't find any specific idea from other answers which is treating base64 string as a actual file.

I used 'request' package from Npm, to send a file to other server by http, multipart protocol.

The code below is working well, read a file from actual file by 'fs' package and send it by ReadStream object by createReadStream method.

(The codes is coffeescript)

#working
res = request.postSync 'http://anotherUrl/uploadDocument',
  formData: file: fs.createReadStream('/path/' + 'myfile.doc')  

What I want to do is creating a same ReadStream object by fs module from a file Based64 encoded String.

I tested something like this, but it's not working properly.

#not working
res = request.postSync 'http://anotherUrl/uploadDocument',
  formData: file: new Buffer(base64EncodedString, 'base64')

#not working
res = request.postSync 'http://anotherUrl/uploadDocument',
  formData: file: _base64ToArrayBuffer(base64EncodedString)

#not working
res = request.postSync 'http://anotherUrl/uploadDocument',
  formData: file: convertDataURIToBinary(base64EncodedString)

##(used function)
_base64ToArrayBuffer = (base64) ->
  binary_string = require('atob')(base64)
  len = binary_string.length
  bytes = new Uint8Array(len)
  i = 0
  while i < len
    bytes[i] = binary_string.charCodeAt(i)
    i++
  bytes.buffer

convertDataURIToBinary = (dataURI) ->
  BASE64_MARKER = ';base64,'
  base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length
  base64 = dataURI.substring(base64Index)
  raw = require('atob')(base64)
  rawLength = raw.length
  array = new Uint8Array(new ArrayBuffer(rawLength))
  i = 0
  while i < rawLength
    array[i] = raw.charCodeAt(i)
    i++
  array

question conclusion

The 'base64EncodedString' is validated by decode & creating file, so i don't doubt it is the matter, so I think I could have this achievement with write file from base64 and read it again with fs module, but I believe that's not the proper way.

The point of question is, 1. How could I send the base64encoded string as a ReadStream object properly in this case 2. How could I figure out relationship clearly between buffer and dataview(uint8array ...) something like that

Thanks in advance.

appendix

From @Alex Nikulin 's comment, I've tested stream-buffers package.

streamBuffers = require('stream-buffers')
myReadableStreamBuffer = new (streamBuffers.ReadableStreamBuffer)(
  frequency: 10
  chunkSize: 2048)
myReadableStreamBuffer.put base64.decode example
myReadableStreamBuffer.stop()

And when I tried bellow it failed again, and the 'AnotherUrl' returns Error message like this, 'unexpected end of part'

res = request.postSync 'http://anotherUrl/uploadDocument',
  formData: file: myReadableStreamBuffer

I figured out the myReadableStreamBuffer object is Readable object, so it might be different with ReadStream object. Can I get it as a ReadStream from myReadableStreamBuffer?

Upvotes: 1

Views: 17248

Answers (1)

Alex Nikulin
Alex Nikulin

Reputation: 8679

Try this

  //if you need just a buffer
  var base64ToBuffer = function(base64) {

        var byteString = new Buffer(base64, 'base64').toString('binary');

        var ab = new Buffer(byteString.length);
        var ia = new Uint8Array(ab);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }

        return ab;
  }
//if you need a stream, not a buffer
var stream = require('stream');

// Initiate the source
var bufferStream = new stream.PassThrough();

// Write your buffer
bufferStream.end(base64ToBuffer(base64));
bufferStream.pipe( process.stdout );

Upvotes: 3

Related Questions