我正在尝试循环访问多个输入文件选择元素
<label class="btn btn-success btn-md rounded-1" for="galleryFile">Create Album</label>
<input type="file" name="galleryFile[]" id="galleryFile" class="d-none" multiple accept="image/*">
并将所有选定的映像保存到 AWS s3
public function sendToCloud($file, $folder, $prefix) {
$filePath = Auth::user()->userid . '/' .$folder.'/' . $prefix;
$extension = $file->getClientOriginalExtension();
$filename = $filePath . time() . '.' . $extension;
Storage::disk('s3')->put($filename, fopen($file, 'r+'), 'public');
return Storage::disk('s3')->url($filename);
}
$unikPath = uniqid();
foreach ($request->file('galleryFile') as $key => $file) {
if ($key == array_key_last($request->file('galleryFile'))) {
$galleryUrl .= $this->sendToCloud($file, $unikPath . '/gallery', 'img_');
} else {
$galleryUrl .= $this->sendToCloud($file, $unikPath . '/gallery', 'img_') . ' | ';
}
}
在我的本地机器上,它工作得很好,让我相信这不是我的代码或 laravel 单独的问题,但是当我部署到 heroku 时,上传行为发生了变化。它在 heroku 上的作用是
如果我选择要上传的 10 张图像,它会随机选择其中 2 张图像并将其保存到 S3 中,并返回这 3 张图像的 S10 URL。
我感谢任何关于如何解决此问题的正确方向的帮助。
提前谢谢。
在我发布这个答案时,你已经写了一个答案来解释你的解决方案。 然而,更好的解决方案是——
- 使用
random_bytes
(连同bin2hex
(而不是uniqid
生成随机文件名,以及 - 检查您是否使用
fopen($file, ...)
打开了现有文件,如果是,请生成不同的文件名以避免覆盖现有文件名。
此外,您在答案中给出的解决方案是脆弱的 - 它假设在应用程序运行时系统时间永远不会更改,由于许多原因,情况可能并不总是如此,包括服务器时钟同步。另请参阅uniqid
的文档。
更新的答案
听从 @Peter O 的建议,我使用bin2hex(random_bytes(7))
为每个文件生成唯一的名称。这可以防止图像被下一个图像覆盖,而无需sleep(1)
。
public function sendToCloud($file, $folder, $prefix) {
$filePath = Auth::user()->userid . '/' .$folder.'/' . $prefix;
$extension = $file->getClientOriginalExtension();
$filename = $filePath . bin2hex(random_bytes(7)) . '.' . $extension;
Storage::disk('s3')->put($filename, fopen($file, 'r+'), 'public');
return Storage::disk('s3')->url($filename);
}
以前的答案
所以我能够解决这个问题。经过多次试验,我意识到所有图像实际上都在处理并发送到 s3,但我只能看到两个,因为处理速度使图像覆盖了以前具有相同名称的图像。
如何?
PHPuniqid()
函数根据微时间生成一个唯一的 ID,三个图像可以同时处理,这意味着它们都将基于 uniqid(( 函数具有相同的值。
我是如何解决的
我在foreach
循环中添加了一个 sleep 函数,将执行延迟 1 秒,让程序有时间生成新的唯一名称。
foreach ($request->file('galleryFile') as $key => $file) {
if ($key == array_key_last($request->file('galleryFile'))) {
$galleryUrl .= $this->sendToCloud($file, $unikPath . '/gallery', 'img_');
} else {
$galleryUrl .= $this->sendToCloud($file, $unikPath . '/gallery', 'img_') . ' | ';
sleep(1);
}
}
我希望有一天这对某人有所帮助。