Я нашел решение, которое использует jQuery и код C # позади страниц. Вот часть jQuery:
$.getJSON('_vti_bin/listdata.svc/<NAME OF LIST (FORMATTED FOR LISTDATA.SVC)>', function(data){
$.each(data.d.results, function(index, value){
$.get('<NAME OF LIST>/'+value.Title+"?noredirect=true", function(info){
$.post('<PATH TO filecreator.aspx>, {file: $(info).find('[nodeName="my:memo"]').text()}, function(data){
$('#response').html(data);
});
});
});
});
HTML является достаточно простым <div id="response"></div>
, предназначенным только для получения данных.
Вот файл filecreator.aspx:
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Text" %>
<script runat="server">
public void Page_Load(object sender, EventArgs e){
int fileSize, nameLength;
string name = "";
byte[] decodedData;
HttpContext c = HttpContext.Current;
string data64 = c.Request["file"];
if(data64==""){
return;
}
byte[] data = Convert.FromBase64String(data64);
using(MemoryStream ms = new MemoryStream(data)){
BinaryReader reader = new BinaryReader(ms);
byte[] header = new byte[16];
header = reader.ReadBytes(header.Length);
fileSize = (int)reader.ReadUInt32();
nameLength = (int)reader.ReadUInt32() * 2;
byte[] fileName = reader.ReadBytes(nameLength);
Encoding enc = Encoding.Unicode;
name = enc.GetString(fileName, 0, nameLength -2);
decodedData = reader.ReadBytes(fileSize);
}
string filePath = Server.MapPath("/temp/"+name);
if(File.Exists(filePath)){
File.Delete(filePath);
}
FileStream fs = new FileStream(filePath, FileMode.CreateNew);
BinaryWriter writer = new BinaryWriter(fs);
writer.Write(decodedData);
writer.Close();
fs.Close();
Response.Write("<a href=\"http://sharept03sb1/services/?download.aspx?file="+name+"\">"+name+"</a><br />");
}
</script>
И, наконец, это файл download.aspx, который запускает загрузку, сейчас он уязвим для lfi, и я отмечу, где это должно быть исправлено:
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Text" %>
<script runat="server">
public void Page_Load(object sender, EventArgs e){
string name = Request.QueryString["file"]; // HERE: Make sure to prevent lfi via directory traversal :)
FileStream fs = File.Open(Server.MapPath("/temp/"+name), FileMode.Open);
byte[] file = new byte[fs.Length];
fs.Read(file, 0, Convert.ToInt32(fs.Length));
fs.Close();
Response.AddHeader("Content-disposition", "attachment; filename=" + name);
Response.ContentType = "application/octet-stream";
Response.BinaryWrite(file);
Response.End();
}
</script>
Пара советов:
- Если вы что-то говорите о неработающих блоках кода, обязательно изучите PageParserPaths в файле sharepoint web.config. Вам нужно это изменить.
- Это обеспечивает только ссылки загрузки для каждого вложения в библиотеке документов, содержащей формы infopath. Конечно, вы можете использовать параметризованные запросы для фильтрации определенных данных.