我试图在不实际使用用户输入的文件的情况下伪造文件上传。文件的内容将从字符串动态生成。
这可能吗?以前有人这样做过吗?是否有可用的示例/理论?
澄清一下,我知道如何使用隐藏的 iframe 和朋友使用 AJAX 技术上传文件 - 问题是上传不在表单中的文件。
我正在使用 ExtJS,但 jQuery 也是可行的,因为 ExtJS 可以插入它(ext-jquery-base)。
我试图在不实际使用用户输入的文件的情况下伪造文件上传。文件的内容将从字符串动态生成。
这可能吗?以前有人这样做过吗?是否有可用的示例/理论?
澄清一下,我知道如何使用隐藏的 iframe 和朋友使用 AJAX 技术上传文件 - 问题是上传不在表单中的文件。
我正在使用 ExtJS,但 jQuery 也是可行的,因为 ExtJS 可以插入它(ext-jquery-base)。
如果您不需要对旧浏览器的支持,您可以使用 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 (IE10+)
为什么不直接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));
}
服务器上的处理程序脚本只是将文件数据写入文件。
编辑
文件上传仍然是具有不同内容类型的 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);
}
如果你想发送额外的数据,你只需用边界分隔每个部分,并描述每个部分的 content-disposition 和 content-type 标题。每个标题由一个换行符分隔,正文与标题由一个额外的换行符分隔。当然,以这种方式上传二进制数据会稍微困难一些:-)
进一步编辑:忘记提及,确保任何边界字符串不在您发送的文本“文件”中,否则它将被视为边界。
只是分享最终结果,它有效 - 并且具有添加/删除参数的简洁方法,无需硬编码任何内容。
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
}
});
这经过测试可以在所有现代浏览器上运行,包括但不限于:
文件上传只是一个POST
文件内容正确编码并带有特殊multipart/formdata
标头的请求。您需要使用它,<input type=file />
因为您的浏览器安全性禁止您直接访问用户磁盘。
由于您不需要读取用户磁盘YES,您可以使用 Javascript 伪造它。这将只是一个XMLHttpRequest
. 要伪造“真实”上传请求,您可以安装Fiddler
并检查您的传出请求。
您需要正确编码该文件,因此此链接非常有用:RFC 2388:从表单返回值:multipart/form-data
使用 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
});