播放:如何在上传后第一次请求时防止图像 src 出现 404
Play: How to prevent 404 on image src on first request after upload
我有一个包含 2 个文本和 1 个文件输入的简单表单
@helper.form(action = routes.CharactersController.newCharacter(), 'enctype -> "multipart/form-data") {
@helper.inputText(field = characterForm("characterName"))
@helper.inputText(field = characterForm("characterRealName"))
@helper.inputFile(field = characterForm("characterImage"))
<p>
<input type="submit">
</p>
}
在 newCharacter 操作中,我将文件移动到资产文件夹。
Http.MultipartFormData body = request().body().asMultipartFormData();
Http.MultipartFormData.FilePart<File> picture = body.getFile("characterImage");
File file = picture.getFile();
file.renameTo(new File(LinkUtil.getCharacterUploadPath(), imageName + ".jpg"));
然后重定向到 /show 页面以显示新输入的字符
return redirect(routes.CharactersController.show(character.id, OrderType.MAIN.name()));
在新加载的页面上,我只看到一张损坏的图片,并在控制台中看到该图片的 404。当我重新加载页面时,图像按预期呈现。
那么当我重定向时哪个部分没有准备好?是 renameTo 还是游戏需要一些时间来找到新资产?
以及如何确保在重定向之前一切就绪?
编辑:
改进我的问题
我正在使用 play 2.5
LinkUtil.getCharacterUploadPath() 解析为 "public/images/characters/"
我将图像嵌入到我的展示模板中,如下所示:
<img src="@character.getImagePath">
然后解析为“/assets/images/characters/imagename.jpg”
编辑 2:进一步调查:
当我在 newCharacter 操作中使用 file.exists() 之类的东西检查新路径的文件系统时,我明白了。所以 rename/moving 部分似乎完成了。
但是,如果我尝试通过 environment
获取资源
environment.getResource("relativePathToFile");
它是空的。即使在 while 循环中,资源也保持为空。这似乎表明该文件尚未真正添加到类路径中。不幸的是,无论我在操作中停留多长时间,资源始终为空。但是当我让线程休眠 2000 毫秒,然后在显示操作中再次检查资源时,它得到了正确的解决。但前提是我要等 2 秒。
另一个测试是在图像上使用 onerror="window.location.reload()"。这导致在找到图像之前重新加载大约 5-10 次。
所以这绝对是一个时间问题,但是让线程休眠任意时间感觉是完全错误的。
必须有一种方法来确保该文件在类路径中可用。
每个 hint/idea 都受到赞赏。
我成功了!首先我上面的方法是有缺陷的。
获取上传的图像,将它们放入 public 文件夹并尝试使用 AssetController 为它们提供服务在生产构建中不起作用。 public 文件夹中的所有内容都打包到一个 .jar 文件中。一些快速测试暗示我从上面重命名不会将图像放在我期望的位置。
所以这是我的解决方案:
定义新路由:
GET /files/*file controllers.Images.serve(file)
在操作中使用文件系统上的绝对路径
public class Images extends Controller {
public Result serve(String file) {
return ok(new java.io.File("/var/www/files/" + file));
}
}
像这样访问文件
<img src="/files/images/characters/imagename.jpg">
图像可在重定向请求中立即访问。
我对问题延迟的猜测是,play 会尝试编译添加到类路径中的所有内容,然后再使其可访问
我有一个包含 2 个文本和 1 个文件输入的简单表单
@helper.form(action = routes.CharactersController.newCharacter(), 'enctype -> "multipart/form-data") {
@helper.inputText(field = characterForm("characterName"))
@helper.inputText(field = characterForm("characterRealName"))
@helper.inputFile(field = characterForm("characterImage"))
<p>
<input type="submit">
</p>
}
在 newCharacter 操作中,我将文件移动到资产文件夹。
Http.MultipartFormData body = request().body().asMultipartFormData();
Http.MultipartFormData.FilePart<File> picture = body.getFile("characterImage");
File file = picture.getFile();
file.renameTo(new File(LinkUtil.getCharacterUploadPath(), imageName + ".jpg"));
然后重定向到 /show 页面以显示新输入的字符
return redirect(routes.CharactersController.show(character.id, OrderType.MAIN.name()));
在新加载的页面上,我只看到一张损坏的图片,并在控制台中看到该图片的 404。当我重新加载页面时,图像按预期呈现。
那么当我重定向时哪个部分没有准备好?是 renameTo 还是游戏需要一些时间来找到新资产? 以及如何确保在重定向之前一切就绪?
编辑: 改进我的问题
我正在使用 play 2.5
LinkUtil.getCharacterUploadPath() 解析为 "public/images/characters/"
我将图像嵌入到我的展示模板中,如下所示:
<img src="@character.getImagePath">
然后解析为“/assets/images/characters/imagename.jpg”
编辑 2:进一步调查:
当我在 newCharacter 操作中使用 file.exists() 之类的东西检查新路径的文件系统时,我明白了。所以 rename/moving 部分似乎完成了。 但是,如果我尝试通过 environment
获取资源environment.getResource("relativePathToFile");
它是空的。即使在 while 循环中,资源也保持为空。这似乎表明该文件尚未真正添加到类路径中。不幸的是,无论我在操作中停留多长时间,资源始终为空。但是当我让线程休眠 2000 毫秒,然后在显示操作中再次检查资源时,它得到了正确的解决。但前提是我要等 2 秒。
另一个测试是在图像上使用 onerror="window.location.reload()"。这导致在找到图像之前重新加载大约 5-10 次。
所以这绝对是一个时间问题,但是让线程休眠任意时间感觉是完全错误的。 必须有一种方法来确保该文件在类路径中可用。
每个 hint/idea 都受到赞赏。
我成功了!首先我上面的方法是有缺陷的。
获取上传的图像,将它们放入 public 文件夹并尝试使用 AssetController 为它们提供服务在生产构建中不起作用。 public 文件夹中的所有内容都打包到一个 .jar 文件中。一些快速测试暗示我从上面重命名不会将图像放在我期望的位置。
所以这是我的解决方案:
定义新路由:
GET /files/*file controllers.Images.serve(file)
在操作中使用文件系统上的绝对路径
public class Images extends Controller {
public Result serve(String file) {
return ok(new java.io.File("/var/www/files/" + file));
}
}
像这样访问文件
<img src="/files/images/characters/imagename.jpg">
图像可在重定向请求中立即访问。
我对问题延迟的猜测是,play 会尝试编译添加到类路径中的所有内容,然后再使其可访问