如何将纯JavaScript对象转换为File对象?

时间:2015-09-27 20:49:45

标签: javascript json file-upload meteor

我遇到需要在变量中存储文件信息(File对象)的情况,但我首先需要JSON.stringify它。这不适用于File个对象:

> JSON.stringify(new File([], null))
« "{}"

所以我需要做的是,获取用户上传的文件,将其转换为普通对象,以字符串格式存储,然后再将其拉出JSON.parse,然后将其转换回File。将它转换为普通对象很简单,但是将它恢复到File对象是我找不到任何方法可以实现的。

补充说明:

所以,让我们说我已将File的属性复制到普通对象中:

{
  "lastModified": 1443077616000,
  "lastModifiedDate": "2015-09-24T06:53:36.000Z",
  "name": "Action Items.zip",
  "size": 3619135,
  "type": "application/zip"
}

我只需将其转换回File对象。

1 个答案:

答案 0 :(得分:0)

基于此评论(How to convert a plain JavaScript object to a File object?),您只需要一个字符串

使用FileReader API将文件转换为DataURL

var fileReader = new FileReader();

// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function(evt) {
    // Read out file contents as a Data URL
    var result = evt.target.result;

    // do whatever with RESULT
    // JSON or whatever

};

// Load blob (File inherits from BLOB) as Data URL
fileReader.readAsDataURL(blob);

使用此功能https://github.com/ebidel/filer.js/blob/master/src/filer.js#L131-L158 将DataURL转换回文件。

/**
 * Creates and returns a blob from a data URL (either base64 encoded or not).
 *
 * @param {string} dataURL The data URL to convert.
 * @return {Blob} A blob representing the array buffer data.
 */
dataURLToBlob: function(dataURL) {
    var BASE64_MARKER = ';base64,';
    if (dataURL.indexOf(BASE64_MARKER) == -1) {
        var parts = dataURL.split(',');
        var contentType = parts[0].split(':')[1];
        var raw = decodeURIComponent(parts[1]);

        return new Blob([raw], {
            type: contentType
        });
    }

    var parts = dataURL.split(BASE64_MARKER);
    var contentType = parts[0].split(':')[1];
    var raw = window.atob(parts[1]);
    var rawLength = raw.length;

    var uInt8Array = new Uint8Array(rawLength);

    for (var i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }

    return new Blob([uInt8Array], {
        type: contentType
    });
}

(你可以在任何地方用文件替换Blob,因为文件继承自Blob)

以下是我如何获取用户删除的文件,将其转换为base64字符串,保存它(没有localStorage因为沙盒)以及稍后取回字符串并将其转换回文件的示例这是由用户发送的。 这不是你想要的吗?

var drop = document.getElementById('drop'),
		transform = document.getElementById('transform');

	drop.addEventListener('dragover', function (e) {
		e.stopPropagation();
	    e.preventDefault();
	    e.dataTransfer.dropEffect = 'copy';
	});

	var originalFile = null;
	drop.addEventListener('drop', function (e) {
	   e.preventDefault();
	    e.stopPropagation();
	    originalFile = event.dataTransfer.files[0];
	    console.log('originalFile', originalFile);
	    fileToURLData(originalFile);
	}, false);

    var storage = {};
	function fileToURLData(file) {
		var fileReader = new FileReader();

		// onload needed since Google Chrome doesn't support addEventListener for FileReader
		fileReader.onload = function(evt) {
		    // Read out file contents as a Data URL
		    var result = evt.target.result;

		    /*localStorage.setItem('file-data', JSON.stringify({
		    	dataURL: result,
				name: file.name,
		    	lastModified: file.lastModified,
				lastModifiedDate: file.lastModifiedDate,
				type: "image/jpeg"
		    }));*/
          storage = JSON.stringify({
		    	dataURL: result,
				name: file.name,
		    	lastModified: file.lastModified,
				lastModifiedDate: file.lastModifiedDate,
				type: "image/jpeg"
		    })

		    console.log('File dataURL',result);
		    // do whatever with RESULT
		    // JSON or whatever


		    transform.className = 'show';
		    drop.className = 'hide';

		};

		// Load blob (File inherits from BLOB) as Data URL
		fileReader.readAsDataURL(file);
	}

	function dataURLToFile(dataURL, name, data) {
	    var BASE64_MARKER = ';base64,';
	    if (dataURL.indexOf(BASE64_MARKER) == -1) {
	        var parts = dataURL.split(',');
	        var raw = decodeURIComponent(parts[1]);

	        return new File([raw], name, data);
	    }

	    var parts = dataURL.split(BASE64_MARKER);
	    var raw = window.atob(parts[1]);
	    var rawLength = raw.length;

	    var uInt8Array = new Uint8Array(rawLength);

	    for (var i = 0; i < rawLength; ++i) {
	        uInt8Array[i] = raw.charCodeAt(i);
	    }

	    return new File([uInt8Array], name, data);
	}

	transform.addEventListener('click', function (e) {
		e.preventDefault();
		e.stopPropagation();

		var fileData= JSON.parse(storage); //localStorage.getItem('file-data')),
			dataURL = fileData['dataURL'],
			name = fileData.name;

		delete fileData.dataURL;
		delete fileData.name;

		console.log(dataURL, name, fileData);
		var file = dataURLToFile(dataURL, name, fileData);
		console.log('convertedFile', file);
		console.log('originalFile', originalFile);
		console.log('originalFile === convertedFile ? ', originalFile === file);
        console.log('different files, same values');
	
		alert('DATAURL HAS BEEN CONVERTED BACK TO FILE - SEE CONSOLE');


	}, false);
html, html {
    width: 100%;
    height: 100%;   
    min-height: 500px;
    text-align: center; 
    font-size: 50px;
}
#drop {
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
}

#drop.hide {
	display: none;
}

#transform {
	display: none;
}

#transform.show {
	display: block;
}
<div id='drop'>DROP FILE HERE</div>
<button id='transform'>Transform back to file</div>