我正在开发一个asp.net webforms网站。网站结构:
/
capabilities/
capability-A/
style.css
images/
imageA.png
imageB.png
capability-B/
style.css
images/
imageC.png
imageD.png
...
在发布版本中,所有style.css
文件被合并并放入/style.css
文件中。因为他们可能会引用相应capability/images
文件夹中的图像(使用相对路径),所有图像都会复制到/images
文件夹中。
在调试版本中,结构不会改变(css文件没有组合等)。
当我尝试在页面上引用这些图像时,问题就出现了问题 - 图像路径在调试和发布版本中有所不同(例如/capabilities/capability-A/images/foo.png
用于调试,/images/foo.png
用于发布)。
我想到的一个非常糟糕的想法是每次检查HttpContext.Current.IsDebuggingEnabled
并放置不同的图像路径。
另一个 - 使用绝对路径引用所有图像,而不是将图像复制到/images
文件夹。使用这种方法,我无法在不改变内容的情况下将css重命名/移动到任何地方。
第三个是始终引用调试版路径,并且在每个版本构建中用正确的路径替换那些调试版路径(但我希望有一个更简单的方法)。
如何在合并css文件后解决此引用图像问题?
答案 0 :(得分:1)
为什么不使用一些辅助函数来输出图像路径 - 辅助函数可以获取图像的站点相对路径并按照调试版本(使用条件语句#if
)输出它并折叠释放路径建立。例如,
public string GetImagePath(string url)
{
#if DEBUG
return "/images/" + url;
#else
return "/images/" + url.Substring(url.LastIndexOf(”/”) + 1);
#endif
}
使用它,例如
<img src='<%= GetImagePath("/capabilities/capability-A/images/foo.png") %>'
编辑:另一种选择是通过简单的http处理程序(如
)提供所有图像<%@ WebHandler Language="C#" Class="ImageHandler" %>
using System;
using System.Web;
public class ImageHandler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
// get relative image path (or have some key to image mapping logic)
var path = request.QueryString["q"];
// map image path
#if DEBUG
#else
path = System.IO.Path.GetFileName(path);
#endif
// get the physical path
path = Path.Combine(context.Server.MapPath("~/Images"), path);
// Emit cache headers (recommended)
...
// transmit the image file
context.Response.TransmitFile(path);
}
}
答案 1 :(得分:0)
好的,我找到了解决方案。我决定将图像保留在其文件夹中,并用绝对路径替换css文件中的相对路径,而不是在发布版本中复制图像和替换页面中的路径。在组合文件之前进行替换,以便replacer-script可以获得有关css文件所在位置的信息以生成绝对路径。我使用来自msbuild社区任务的Script和FileUpdate任务的Web部署项目来实现这一点。脚本任务用于创建需要插入每个相对路径前面的绝对URL部分。 FileUpdate任务用于使用正则表达式替换所有相对路径及其绝对模拟。
这是msbuild脚本的一部分:
<Target Name="BeforeBuild">
<CallTarget Targets="CombineAndMinifyCssAndJavaScript" />
</Target>
<Target Name="_InitCombineAndMinifyCssAndJavaScript">
<ItemGroup>
<!-- These are the CSS files that will be combined. -->
<InputCssFiles Include="$(CopyBeforeBuildTargetPath)\capabilities\**\*.css" />
</ItemGroup>
</Target>
<Target Name="_CorrectResourceUrlsInCSSFiles"
Outputs="%(InputCssFiles.Identity)"
DependsOnTargets="_InitCombineAndMinifyCssAndJavaScript"
Condition=" '@(InputCssFiles)' != '' ">
<PropertyGroup>
<InputCssFileDir>%(InputCssFiles.RootDir)%(InputCssFiles.Directory)</InputCssFileDir>
<CodeToExtractAbsoluteUrlPath>
<![CDATA[
public static String ScriptMain()
{
String cssDir = @"$(InputCssFileDir)".ToLowerInvariant();
String websiteDir = @"$(CopyBeforeBuildTargetPath)".ToLowerInvariant();
cssDir = cssDir.TrimEnd(new char[] { '\\' });
websiteDir = websiteDir.TrimEnd(new char[] { '\\' });
if (!cssDir.StartsWith(websiteDir))
{
throw new ArgumentException(String.Format(
"CSS file directory ({0}) should be somewhere under website root ({1}).", cssDir, websiteDir));
}
String absoluteUrlPath = (cssDir.Remove(0, websiteDir.Length) + "\\").Replace('\\', '/');
return absoluteUrlPath;
}
]]>
</CodeToExtractAbsoluteUrlPath>
</PropertyGroup>
<Script Language="C#" Code="$(CodeToExtractAbsoluteUrlPath)">
<Output PropertyName="AbsoluteUrlPath" TaskParameter="ReturnValue" />
</Script>
<!--
Regex is:
url \s*
\( \s*
['"]
([^/'":][^'":]*)
['"]
\s* \)
-->
<FileUpdate
Files="%(InputCssFiles.FullPath)"
Regex="url\s*\(\s*['"]([^/'":][^'":]*)['"]\s*\)"
ReplacementText="url('$(AbsoluteUrlPath)$1')" />
</Target>