我该如何将输入的文件对象序列化为JSON?

60

我想将一个HTML输入文件转换为以下格式的JSON字符串:

var jsonString = JSON.stringify(file);
console.log( file );
console.log( jsonString );
现在,在我的 Firebug 中,它记录为:
File { size=360195, type="image/jpeg", name="xyz.jpg", mehr...} 
Object {}

为什么jsonString是空的?

背景信息:我想使用JSONP将文件引用发送到另一个PHP服务器。

其他信息:我只想将文件指针(引用)转换为字符串,以通过GET方式发送。

7个回答

31

在Chrome、Firefox和Safari中,不能直接使用JSON.stringifyFile对象转换为JSON。

您可以通过一些方法绕过去,使用JSON.stringifyFile对象转换为字符串。

例如:

// get File Object  
var fileObject = getFile();

// reCreate new Object and set File Data into it
var newObject  = {
   'lastModified'     : fileObject.lastModified,
   'lastModifiedDate' : fileObject.lastModifiedDate,
   'name'             : fileObject.name,
   'size'             : fileObject.size,
   'type'             : fileObject.type
};  
 
// then use JSON.stringify on new object
JSON.stringify(newObject);

你可以在你的File对象上添加toJSON()行为

例如:

// get File Object  
var fileObject = getFile();

// implement toJSON() behavior  
fileObject.toJSON = function() { return {
   'lastModified'     : myFile.lastModified,
   'lastModifiedDate' : myFile.lastModifiedDate,
   'name'             : myFile.name,
   'size'             : myFile.size,
   'type'             : myFile.type 
};}  
 
// then use JSON.stringify on File object
JSON.stringify(fileObject);

注意:使用POST HTTP方法将File对象发送到服务器。

实际上,在Chrome中,您也无法将File对象字符串化。 - ffxsam
是的,现在我已经在Chrome中使用File对象测试了JSON.stringify,但它不起作用。但是当我回答这个问题时,它是可以工作的。 - ahmed hamdy
啊...什么?文件API不应该转换为字符串。请参见:https://dev59.com/oGIk5IYBdhLWcg3wn_RF - wle8300
@williamle8300,您错过了问题的一部分,即他想将“文件”对象作为JSON请求发送到“PHP”服务器,因此他想要将“文件”对象字符串化。 您提供的问题链接还涉及另一个情况,而且接受的答案说:“(您无法序列化“文件”对象)”->(与此问题相同)。 我的答案只是将“文件”对象字符串化的解决方法。 - ahmed hamdy
@williamle8300 是的,我知道,我的答案可以解决这个问题。 - ahmed hamdy
显示剩余2条评论

11

使用FileReader API读取文件内容。File对象并不包含文件内容(它只是一个指针,让您以后可以读取它)。

您可以查看这篇HTML5Rocks文章,了解更多关于该API的用法。

var file = getAFile( );

var success = function ( content ) {
  console.log( JSON.stringify( content ) ); }

var fileReader = new FileReader( );
fileReader.onload = function ( evt ) { success( evt.target.result ) };
fileReader.readAsText( file );

谢谢您的回答。我想将指针发送到另一台服务器。因此,我必须将文件指针转换为字符串。您有什么想法吗? - peacemaker
你读了这篇文章吗?evt.target.result是一个包含文件内容的字符串。由于安全原因,使用FileReader API是获取它的唯一方法。 - Maël Nison
我认为这不是我的项目的解决方案。问题在于我将使用GET发送字符串。如果文件大小为500 MB,字符串的大小太长了。 - peacemaker
那么,不要使用GET发送它?我不确定你想要什么。如果你只需要发布一个文件,请使用FormData,而不是JSON,因为前者可以在不需要在RAM中缓冲其内容的情况下简化文件上传。 - Maël Nison
1
你不能通过GET方式发送文件。这里应该使用POST方式,我不明白为什么你更喜欢使用GET方式。网络服务器永远不会愿意解析一个500Mo的URL。 - Maël Nison

4

你只需要一个自定义替换器:

function stringify(obj) {
    const replacer = [];
    for (const key in obj) {
        replacer.push(key);
    }
    return JSON.stringify(obj, replacer);
}

const json = stringify(file);
console.log(file);
console.log(json);

现在您应该看到:
File {name: "xyz.jpg", type: "image/jpeg", size...}
'{"name":"xyz.jpg","type":"image/jpeg","size"...}'

4
如果还有人在寻找解决方案,请参阅其他帖子上我的答案和JSFiddle上的可工作示例
JS:
function getFiles(){
    var files = document.getElementById("myFiles").files;
    var myArray = [];
    var file = {};

    console.log(files); // see the FileList

    // manually create a new file obj for each File in the FileList
    for(var i = 0; i < files.length; i++){

      file = {
          'lastMod'    : files[i].lastModified,
          'lastModDate': files[i].lastModifiedDate,
          'name'       : files[i].name,
          'size'       : files[i].size,
          'type'       : files[i].type,
      } 

      //add the file obj to your array
      myArray.push(file)
    }

    //stringify array
    console.log(JSON.stringify(myArray));
}

HTML:

<input id="myFiles" type="file" multiple onchange="getFiles()" />

1
我应该如何从后端的这个 file 对象中获取文件? - Shahriar Rahman Zahin

1

我想到了这个函数,用于图像输入,而不是循环遍历或逐个提取每个键。

const fileObject = e.target.files[0];

重要通知
//dont use shorthand for of loop
for (const [key, value] in Object.entries(x)) 
it can't loop through a file object in JS 

请使用以下代码。
const imageObject = {};

for (const key in fileObject) {
    const value = fileObject[key];
    const notFunction = typeof value !== "function";
    notFunction && (imageObject[key] = value);
}

console.log(imageObject) // => should give you a normal JS object now

-1

当您传递一个JSON字符串时,Javascript会在内部将其转换为JSON对象,因此无需解析它。

在处理JSON文件时,请按照以下步骤进行 ->

$('#inp_import_template')[0].files[0]

现在你的json文件已经转换为json对象(Javascript)。

这个回答如何解决问题? - winklerrr

-3
var obj = {
  name: 'dashu3f'
};

var stringObj = JSON.stringify(obj);
console.log(typeof stringObj);
console.log(stringObj);

打开终端,进入该文件夹并运行node json.js


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接