Javascript:上传文件...没有文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2198470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript: Uploading a file... without a file
提问by LiraNuna
I am trying to fake a file upload without actually using a file input from the user. The file's content will be dynamically generated from a string.
我试图在不实际使用用户输入的文件的情况下伪造文件上传。文件的内容将从字符串动态生成。
Is this possible? Have anyone ever done this before? Are there examples/theory available?
这可能吗?以前有人这样做过吗?是否有可用的示例/理论?
To clarify, I know how to upload a file using AJAX techniques using a hidden iframe and friends - the problem is uploading a file that is not in the form.
澄清一下,我知道如何使用隐藏的 iframe 和朋友使用 AJAX 技术上传文件 - 问题是上传不在表单中的文件。
I am using ExtJS, but jQuery is feasible as well since ExtJS can plug into it (ext-jquery-base).
我正在使用 ExtJS,但 jQuery 也是可行的,因为 ExtJS 可以插入它(ext-jquery-base)。
采纳答案by Andy E
Why not just use XMLHttpRequest()with POST?
为什么不直接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));
}
The handler script at the server just writes the file data to a file.
服务器上的处理程序脚本只是将文件数据写入文件。
EDIT
File upload is still a http post with a different content type. You can use this content type and separate your content with boundaries:
编辑
文件上传仍然是具有不同内容类型的 http 帖子。您可以使用此内容类型并用边界分隔您的内容:
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);
}
If you want to send additional data, you just separate each section with a boundary and describe the content-disposition and content-type headers for each section. Each header is separated by a newline and the body is separated from the headers by an additional newline. Naturally, uploading binary data in this fashion would be slightly more difficult :-)
如果你想发送额外的数据,你只需用边界分隔每个部分,并描述每个部分的 content-disposition 和 content-type 标题。每个标题由一个换行符分隔,正文与标题由一个额外的换行符分隔。当然,以这种方式上传二进制数据会稍微困难一些:-)
Further edit: forgot to mention, make sure whatever boundary string isn't in the text "file" that you're sending, otherwise it will be treated as a boundary.
进一步编辑:忘了提及,确保您发送的文本“文件”中没有任何边界字符串,否则它将被视为边界。
回答by Josa
If you don't need support for older browsers you can use the FormData Object, which is part of the File API:
如果您不需要对旧浏览器的支持,您可以使用 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);
File Api is supported by all current browsers (IE10+)
当前所有浏览器(IE10+)都支持 File Api
回答by LiraNuna
Just sharing the final result, which works - and has clean way of adding/removing parameters without hardcoding anything.
只是分享最终结果,这是有效的 - 并且具有添加/删除参数的简洁方法,无需硬编码任何内容。
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
}
});
This was tested to work on all modern browsers, including but not limited to:
这经过测试可以在所有现代浏览器上运行,包括但不限于:
- IE6+
- FF 1.5+
- Opera 9+
- Chrome 1.0+
- Safari 3.0+
- IE6+
- FF 1.5+
- 歌剧 9+
- 铬 1.0+
- Safari 3.0+
回答by Rubens Farias
A file upload it's just a POSTrequest with that file content properly encoded and with an special multipart/formdataheader. You need to use that <input type=file />because your browser security forbid you to access user disk directly.
文件上传只是一个POST文件内容正确编码并带有特殊multipart/formdata标头的请求。您需要使用它,<input type=file />因为您的浏览器安全性禁止您直接访问用户磁盘。
As you don't need to read user disk, YES, you can fake it using Javascript. It will be just a XMLHttpRequest. To forge an "authentic" upload request, you can install Fiddlerand inspect your outgoing request.
由于您不需要读取用户磁盘YES,您可以使用 Javascript 伪造它。这将只是一个XMLHttpRequest. 要伪造“真实”上传请求,您可以安装Fiddler并检查您的传出请求。
You'll need to encode that file correctly, so this link can be very useful: RFC 2388: Returning Values from Forms: multipart/form-data
您需要正确编码该文件,因此此链接非常有用:RFC 2388: Returning Values from Forms: multipart/form-data
回答by ixpl0
Easy way to imitate "fake" file upload with jQuery:
使用 jQuery 模仿“假”文件上传的简单方法:
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
});
回答by supercalifragilistichespirali
https://stackoverflow.com/a/2198524/2914587worked for me, after I added an extra '--'before the final boundaryin the payload:
https://stackoverflow.com/a/2198524/2914587对我有用,在我在有效负载'--'的 final 之前添加了一个额外的东西之后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 + '--';
回答by Tom Bartel
I just caught this POST_DATA string with the Firefox TamperData addon. I submitted a form with one type="file"field named "myfile" and a submit button named "btn-submit" with value "Upload". The contents of the uploaded file are
我刚刚使用 Firefox TamperData 插件捕获了这个 POST_DATA 字符串。我提交了一个表单,其中包含一个type="file"名为“myfile”的字段和一个名为“btn-submit”且值为“Upload”的提交按钮。上传文件的内容是
Line One
Line Two
Line Three
So here is the POST_DATA string:
所以这里是 POST_DATA 字符串:
-----------------------------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
I'm not sure what the number means (192642264827446), but that should not be too hard to find out.
我不确定这个数字是什么意思 (192642264827446),但这应该不难发现。

