BuildAction的Content和Resource的区别

很多初学Windows Phone 7开发的朋友经常因为资源文件的BuildAction属性设置不当而导致图片无法显示、多媒体文件无法访问之类的问题。在Windows Phone 7中,资源文件的BuildAction属性通常有Content/Resource/None三个可选值,那么究竟设置为哪一个才合适呢?下面我们就这一问题进行简单的探索。

WhichOneShouldIChoose

疑惑1:BuildAction属性设置为Content/Resource/None的资源有何区别?

这个问题我们通过一个简单的测试来解答。为了容易观察,我们选择两个较大的视频文件(每个10M左右)作为资源文件进行测试。

如图所示,我们添加两个视频文件video1.wmv、video2.wmv到项目中的Medias文件夹。

AddTwoVideoFiles

并分别设置其BuildAction属性为Content、Resource。

SetVideo1ToContentSetVideo2ToResource

按F6键编译项目。然后到项目的bin/Debug文件夹中找到编译生成的xap文件,将其后缀改为zip(对Silverlight有所了解的朋友应该清楚,一个Xap文件实际上就是一个zip压缩包)。

FindXapChangeExtentionName

用压缩软件打开该zip文件,在其中的Medias文件夹中将看到vedio1.wmv文件以独立文件的形式存在于压缩包中(右图)。

那么vieo2.wmv文件哪里去了呢?注意观察左图中DemoCode1.dll文件的大小---10M多!!!你猜的没错,vieo2.wmv就是被嵌入到了这个dll文件中。

OpenZip

那么设置为None的情况又是如何呢?实际上试过之后你会发现,设置为None的资源文件既不会直接打包在xap文件中,也不会嵌入xap中的dll内,编译过程会完全忽略该资源文件。那么以下的探讨中也将忽略BuildAction设置为None的情况。

那么通过以上测试我们可以总结如下:

  • BuildAction属性设置为Conten的文件将被作为独立文件直接打包在xap文件中
  • BuildAction属性设置为Resource的文件将被嵌入到xap包中的dll文件内
  • BuildAction属性设置为None的文件,将不会存以任何形式在于xap包中

疑惑2:BuildAction选择Content还是Resource?

根据目前的使用经验,简单总结如下。

多数情况下,两种形式都可以使用,但是以下情况使用Content更为便捷:

  • 一般情况下,使用Content时,资源文件的URI更为简洁,而Resource相对繁琐一些。
    • e.g.如video1.wmv文件通常可通过URI“/Medias/video1.wmv”访问,
      而video2.wmv则需要“[项目名];component/Medias/video1.wmv"访问(XAML中除外)
  • 由于使用Content时,文件是直接打包在项目中,因此对于需要批量打包生成xap文件的场景,只能用Content。
  • 对于多媒体文件,务必使用Content形式以取得更佳的性能。
    • MSDN文档原文
      “Media processing on Windows Phone 7 is optimized to use files and network streams, but not in-memory streams. This means that any media files included in the application, such as sound effects, should have their Build Action set to Content and notResource.”
      “Windows Phone 上的多媒体处理针对文件和网络流做了优化,而内存流没有。这就意味着包含在应用程序中任何媒体文件,如声音效果等,应该设置其BuildAction属性为Content而不是Resource。”
    • 更详细解释参考WPMind的WP7 Dev 101 【7】 选择BuildAction

对于以下场景,使用Resource可能更合适:

  • 需要避免异步加载的资源文件应当使用Resource
    • e.g.一个典型的场景是Panorama控件的背景图片,如果设置为Content在首次显示页面时会有闪烁。MSDN文档原文
      “If a Panorama control is using an image for the background, its Build Action should be set to Resource; otherwise, it will not appear immediately when the application is first displayed. Setting the Build Action to Content would cause it to be loaded asynchronously.”
      “如果Panorama 控件使用图片作为背景,其BuildAction属性应当色号之为Resource;否则,当应用程序手册显示时图片将不会立即呈现。将BuildAction设置为Content属性会导致其异步加载。”
    • 很多用作背景的图片都和上例相仿
  • 使用Resource可以比Content更好的保护自己Xap包中的资源文件(如自己辛苦设计的图片等)。
    • 这很容易理解,因为Content时资源文件直接以文件形式存在于Xap包中,别人拿到Xap解压后也就拿到了你的资源文件。而Resource时嵌入在dll文件中,获取相对麻烦些(但也不是完全安全)。
  • 需要从C#代码中动态访问的资源文件(如XML文件等),需要设置为Resource。欲了解详情请参考下一课介绍的场景。
好的,针对您的问题,我可以给您提供一些思路和示例代码,帮助您实现这个功能。 首先是学生端和教师端的代码,我们可以使用 `el-upload` 组件来实现文件上传功能。在学生端,我们可以这样写: ```html <template> <el-upload class="upload-demo" action="/upload" :on-success="handleSuccess" :before-upload="beforeUpload" :file-list="fileList" :limit="1" :auto-upload="false" > <el-button slot="trigger" size="small" type="primary">选择文件</el-button> <el-button style="margin-left: 10px;" size="small" type="success" @click="uploadFile" :disabled="fileList.length === 0" > 上传文件 </el-button> </el-upload> </template> <script> export default { data() { return { fileList: [], }; }, methods: { beforeUpload(file) { const isPDF = file.type === 'application/pdf'; const isDOCX = file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; const isLt5M = file.size / 1024 / 1024 < 5; if (!isPDF && !isDOCX) { this.$message.error('只能上传 PDF 或 DOCX 格式的文件'); return false; } if (!isLt5M) { this.$message.error('上传文件大小不能超过 5MB'); return false; } this.fileList = [file]; return false; }, handleSuccess(response) { this.$message.success('上传成功'); this.fileList = []; }, uploadFile() { this.$refs.upload.submit(); }, }, }; </script> ``` 在教师端,我们可以使用类似的代码来展示已上传的文件,并提供下载链接: ```html <template> <div> <el-upload class="upload-demo" action="/download" :file-list="fileList" :limit="1" :auto-upload="false" > <el-button slot="trigger" size="small">查看文件</el-button> </el-upload> <el-button style="margin-left: 10px;" size="small" type="success" @click="downloadFile" :disabled="fileList.length === 0" > 下载文件 </el-button> </div> </template> <script> export default { data() { return { fileList: [], downloadUrl: '', }; }, mounted() { // 模拟已上传的文件 this.fileList = [ { name: '作业.docx', url: 'https://www.example.com/homework.docx', }, ]; }, methods: { downloadFile() { window.open(this.fileList[0].url); }, }, }; </script> ``` 接下来是后端 Spring Boot 的代码,我们可以使用 `MultipartFile` 类型来接收上传的文件,并使用 `java.nio.file.Files` 类将文件保存到本地: ```java @PostMapping("/upload") public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) { // 获取文件名 String fileName = file.getOriginalFilename(); // 获取文件存储路径 String filePath = "/path/to/files/" + fileName; // 将文件保存到本地 try { Files.write(Paths.get(filePath), file.getBytes()); } catch (IOException e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败"); } return ResponseEntity.ok("文件上传成功"); } @GetMapping("/download") public ResponseEntity<Resource> downloadFile() { // 获取文件存储路径 String filePath = "/path/to/files/作业.docx"; // 将文件读取为 Resource Resource resource; try { resource = new UrlResource(Paths.get(filePath).toUri()); } catch (MalformedURLException e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(resource); } ``` 在这个例子中,我们将文件保存到了 `/path/to/files/` 目录下,并提供了一个 `/download` 接口来下载文件。需要注意的是,在生产环境中,我们应该将文件保存到更安全的位置,并实现更严格的访问控制。 希望这些代码能对您有所帮助。如果您还有其他问题,欢迎继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值