Во-первых, давайте проясним, что если вы хотите использовать собственные домены в вашей многосайтовой сети WP, то вам не нужны отдельные папки / установки WordPress для каждого сайта.
Все ваши домены дополнений должны указывать на вашу главную папку мультисайта WP. Например, если example.com является вашим основным доменом сети WP Multisite и он указывает на папку «public_html», то ваши домены дополнения говорят, что domain2.com также должен указывать на ту же папку, которая называется «public_html»
Я не уверен насчет некоторых из ASP.Net аспекты, но я работаю над чем-то похожим, и вы могли бы вместо этого изучить использование RTF. Вы можете использовать замену шаблона в RTF. Например, вы можете добавить тег типа {USER_FIRST_NAME} в документе RTF. Когда пользователь нажимает кнопку загрузки, Ваше приложение может взять информацию из базы данных и заменить каждый экземпляр {USER_FIRST_NAME} данными из базы данных. В настоящее время я делаю это с PHP, и он прекрасно работает. Word откроет RTF без проблем, и это еще одна причина, по которой я выбрал этот метод.
Если вы можете использовать Office 2007, то используйте Open XML API для форматирования документов: http://support.microsoft.com/kb/257757 . Причина, по которой вы должны идти по этому пути, заключается в том, что вы не можете использовать Word Automation в серверной среде. (Вы МОЖЕТЕ, но работать должным образом очень сложно, и ЛЕГКО сломаться).
Если вы не можете идти по пути 2007 года, у меня действительно был довольно хороший успех: я просто открыл шаблон слова в виде потока, нашел и заменил токены и подал их пользователю. По моему опыту, это сработало на удивление хорошо, и ДЕЙСТВИТЕЛЬНО просто реализовать.
Я использовал Aspose.Words для .NET . Это немного дороговато, но работает очень хорошо, и API довольно интуитивно понятен для чего-то, что может быть очень сложным.
Если вы хотите предварительно разработать свои документы (или позволить другим сделать это за вас), любой может поместить поля в документ. Aspose может открыть документ, найти и заполнить поля и сохранить новую заполненную копию для загрузки.
Aspose работает хорошо, но опять же: это дорого.
Определенно избегайте Office Automation в веб-приложениях, насколько это возможно. , Это просто плохо масштабируется.
Мое предпочтительное решение для такого рода проблем - xml: именно здесь я рекомендую WordProcessingML . Вы создаете документ XML в соответствии со схемой, добавляете к нему расширение .doc
, и MS Word открывает его так, как если бы он был встроенным в любой версии еще до Office XP. Это поддерживает большинство функций Word, и таким образом вы можете безопасно свести проблему к замене токенов в текстовом потоке.
Будьте осторожны в поисках дополнительной информации по этому вопросу: между этим и новым форматом на основе XML для Office существует большая путаница 2007. Они не одно и то же.
Этот код работает с текстовыми полями и флажками WordMl. Он основан на индексе, поэтому просто передайте массив строк для всех текстовых полей и массив bool для всех флажков.
public void FillInFields(
Stream sourceStream,
Stream destinationStream,
bool[] pageCheckboxFields,
string[] pageTextFields
) {
StreamUtil.Copy(sourceStream, destinationStream);
sourceStream.Close();
destinationStream.Seek(0, SeekOrigin.Begin);
Package package = Package.Open(destinationStream, FileMode.Open, FileAccess.ReadWrite);
Uri uri = new Uri("/word/document.xml", UriKind.Relative);
PackagePart packagePart = package.GetPart(uri);
Stream documentPart = packagePart.GetStream(FileMode.Open, FileAccess.ReadWrite);
XmlReader xmlReader = XmlReader.Create(documentPart);
XDocument xdocument = XDocument.Load(xmlReader);
List<XElement> textBookmarksList = xdocument
.Descendants(w + "fldChar")
.Where(e => (e.AttributeOrDefault(w + "fldCharType") ?? "") == "separate")
.ToList();
var textBookmarks = textBookmarksList.Select(e => new WordMlTextField(w, e, textBookmarksList.IndexOf(e)));
List<XElement> checkboxBookmarksList = xdocument
.Descendants(w + "checkBox")
.ToList();
IEnumerable<WordMlCheckboxField> checkboxBookmarks = checkboxBookmarksList
.Select(e => new WordMlCheckboxField(w, e, checkboxBookmarksList.IndexOf(e)));
for (int i = 0; i < pageTextFields.Length; i++) {
string value = pageTextFields[i];
if (!String.IsNullOrEmpty(value))
SetWordMlElement(textBookmarks, i, value);
}
for (int i = 0; i < pageCheckboxFields.Length; i++) {
bool value = pageCheckboxFields[i];
SetWordMlElement(checkboxBookmarks, i, value);
}
PackagePart newPart = packagePart;
StreamWriter streamWriter = new StreamWriter(newPart.GetStream(FileMode.Create, FileAccess.Write));
XmlWriter xmlWriter = XmlWriter.Create(streamWriter);
if (xmlWriter == null) throw new Exception("Could not open an XmlWriter to 4311Blank-1.docx.");
xdocument.Save(xmlWriter);
xmlWriter.Close();
streamWriter.Close();
package.Flush();
destinationStream.Seek(0, SeekOrigin.Begin);
}
private class WordMlTextField {
public int? Index { get; set; }
public XElement TextElement { get; set; }
public WordMlTextField(XNamespace ns, XObject element, int index) {
Index = index;
XElement parent = element.Parent;
if (parent == null) throw new NicException("fldChar must have a parent.");
if (parent.Name != ns + "r") {
log.Warn("Expected parent of fldChar to be a run for fldChar at position '" + Index + "'");
return;
}
var nextSibling = parent.ElementsAfterSelf().First();
if (nextSibling.Name != ns + "r") {
log.Warn("Expected a 'r' element after the parent of fldChar at position = " + Index);
return;
}
var text = nextSibling.Element(ns + "t");
if (text == null) {
log.Warn("Expected a 't' element inside the 'r' element after the parent of fldChar at position = " + Index);
}
TextElement = text;
}
}
private class WordMlCheckboxField {
public int? Index { get; set; }
public XElement CheckedElement { get; set; }
public readonly XNamespace _ns;
public WordMlCheckboxField(XNamespace ns, XContainer checkBoxElement, int index) {
_ns = ns;
Index = index;
XElement checkedElement = checkBoxElement.Elements(ns + "checked").FirstOrDefault();
if (checkedElement == null) {
checkedElement = new XElement(ns + "checked", new XAttribute(ns + "val", "0"));
checkBoxElement.Add(checkedElement);
}
CheckedElement = checkedElement;
}
public static void Copy(Stream readStream, Stream writeStream) {
const int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = readStream.Read(buffer, 0, Length);
// write the required bytes
while (bytesRead > 0) {
writeStream.Write(buffer, 0, bytesRead);
bytesRead = readStream.Read(buffer, 0, Length);
}
readStream.Flush();
writeStream.Flush();
}
Не могли бы вы использовать собственную InterOp Framework Microsoft для использования функциональности Word
См. Здесь
В общем, вы захотите чтобы избежать автоматизации Office, а Microsoft даже заявила, что это тоже плохая идея . Однако обычно я использую метод Office Open XML , который был отмечен aquinas .