Javascript:上传文件…没有文件

我试图伪造一个file upload,而没有实际使用用户的文件input。 该文件的内容将从一个stringdynamic生成。

这可能吗? 有没有人曾经这样做过? 有没有可用的例子/理论?

为了澄清,我知道如何使用隐藏的iframe和朋友使用AJAX技术上传文件 – 问题是上传不在表单中的文件。

我使用的是ExtJS,但是jQuery也是可行的,因为ExtJS可以插入它(ext-jquery-base)。

为什么不使用XMLHttpRequest()和POST?

 function beginQuoteFileUnquoteUpload(data) { var xhr = new XMLHttpRequest(); xhr.open("POST", "http://www.mysite.com/myuploadhandler.php", true); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) alert("File uploaded!"); } xhr.send("filedata="+encodeURIComponent(data)); } 

服务器上的处理程序脚本只是将文件数据写入文件。

编辑
file upload仍然是一个不同的内容types的HTTPpost。 您可以使用此内容types,并用边界分隔您的内容:

 function beginQuoteFileUnquoteUpload(data) { // Define a boundary, I stole this from IE but you can use any string AFAIK var boundary = "---------------------------7da24f2e50046"; var xhr = new XMLHttpRequest(); var body = '--' + boundary + '\r\n' // Parameter name is "file" and local filename is "temp.txt" + 'Content-Disposition: form-data; name="file";' + 'filename="temp.txt"\r\n' // Add the file's mime-type + 'Content-type: plain/text\r\n\r\n' + data + '\r\n' + boundary + '--'; xhr.open("POST", "http://www.mysite.com/myuploadhandler.php", true); xhr.setRequestHeader( "Content-type", "multipart/form-data; boundary="+boundary ); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) alert("File uploaded!"); } xhr.send(body); } 

如果要发送其他数据,则只需将每个部分与边界分开,并描述每个部分的内容处置和内容types标题。 每个标题由一个换行符分隔,并且正文通过一个额外的换行符与标题分开。 当然,以这种方式上传二进制数据会稍微困难一点:-)

进一步编辑:忘记提及,确保你发送的文本“文件”中没有任何边界string,否则将被视为边界。

如果您不需要旧版浏览器的支持,则可以使用FormData对象,它是File API的一部分:

 var formData = new FormData(); var blob = new Blob(['Lorem ipsum'], { type: 'plain/text' }); formData.append('file', blob,'readme.txt'); var request = new XMLHttpRequest(); request.open('POST', 'http://example.org/upload'); request.send(formData); 

所有当前浏览器(IE10 +)均支持文件Api

只是分享最后的结果,这是有效的 – 并且有干净的方式添加/删除参数,而不用硬编码任何东西。

 var boundary = '-----------------------------' + Math.floor(Math.random() * Math.pow(10, 8)); /* Parameters go here */ var params = { file: { type: 'text/plain', filename: Path.utils.basename(currentTab.id), content: GET_CONTENT() /* File content goes here */ }, action: 'upload', overwrite: 'true', destination: '/' }; var content = []; for(var i in params) { content.push('--' + boundary); var mimeHeader = 'Content-Disposition: form-data; name="'+i+'"; '; if(params[i].filename) mimeHeader += 'filename="'+ params[i].filename +'";'; content.push(mimeHeader); if(params[i].type) content.push('Content-Type: ' + params[i].type); content.push(''); content.push(params[i].content || params[i]); }; /* Use your favorite toolkit here */ /* it should still work if you can control headers and POST raw data */ Ext.Ajax.request({ method: 'POST', url: 'www.example.com/upload.php', jsonData: content.join('\r\n'), headers: { 'Content-Type': 'multipart/form-data; boundary=' + boundary, 'Content-Length': content.length } }); 

这是testing适用于所有的现代浏览器,包括但不限于:

  • IE6 +
  • FF 1.5+
  • 歌剧9+
  • Chrome 1.0+
  • Safari 3.0+

一个file upload它只是一个POST请求与该文件内容正确编码和一个特殊的multipart/formdata标题。 您需要使用<input type=file />因为您的浏览器安全性禁止您直接访问用户磁盘。

由于您不需要读取用户磁盘,所以您可以使用Javascript来伪造它。 这将只是一个XMLHttpRequest 。 要伪造“真实”的上传请求,您可以安装Fiddler并检查您的传出请求。

您需要正确编码该文件,因此此链接可能非常有用: RFC 2388:从窗体返回值:multipart / form-data

我刚刚用Firefox TamperData插件捕获了这个POST_DATAstring。 我提交了一个名为“myfile”的type="file"字段和一个名为“btn-submit”的提交button,其值为“Upload”。 上传的文件的内容是

 Line One Line Two Line Three 

所以这里是POST_DATAstring:

 -----------------------------192642264827446\r\n Content-Disposition: form-data; \n name="myfile"; filename="local-file-name.txt"\r\n Content-Type: text/plain\r\n \r\n Line \n One\r\n Line Two\r\n Line Three\r\n \r\n -----------------------------192642264827446\n \r\n Content-Disposition: form-data; name="btn-submit"\r\n \r\n Upload\n \r\n -----------------------------192642264827446--\r\n 

我不确定这个数字是什么意思(192642264827446),但是这不应该太难找出来。

https://stackoverflow.com/a/2198524/2914587为我工作后,我在有效载荷的最后;boundary之前添加了一个额外的'--'

 var body = '--' + boundary + '\r\n' // Parameter name is "file" and local filename is "temp.txt" + 'Content-Disposition: form-data; name="file";' + 'filename="temp.txt"\r\n' // Add the file's mime-type + 'Content-type: plain/text\r\n\r\n' + data + '\r\n' + '--' + boundary + '--'; 

用jQuery模仿“假”file upload的简单方法:

 var fd = new FormData(); var file = new Blob(['file contents'], {type: 'plain/text'}); fd.append('formFieldName', file, 'fileName.txt'); $.ajax({ url: 'http://example.com/yourAddress', method: 'post', data: fd, processData: false, //this... contentType: false //and this is for formData type });