You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.7 KiB

1 month ago
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Storage;
1 month ago
use Illuminate\Support\Facades\URL;
1 month ago
class ApplicationFile extends Model
{
protected $fillable = [
'application_id',
'kind',
'disk',
'path',
'original_name',
'size',
'mime',
];
public function application(): BelongsTo
{
return $this->belongsTo(Application::class);
}
public function publicUrl(): string
{
1 month ago
$u = Storage::disk($this->disk)->url($this->path);
return preg_replace('#([^:])//+#', '$1/', $u) ?? $u;
1 month ago
}
1 month ago
/**
* 浏览器下载/「另存为」显示名:优先用户上传时的原始文件名,必要时按存储路径补全扩展名(避免无后缀时落到随机 storage 名)。
*/
public function clientDownloadName(): string
{
$raw = $this->original_name !== null && trim($this->original_name) !== ''
? basename(str_replace(['\\', '/'], '_', $this->original_name))
: '';
$storageExt = strtolower((string) pathinfo($this->path, PATHINFO_EXTENSION));
if ($raw !== '') {
$baseExt = strtolower((string) pathinfo($raw, PATHINFO_EXTENSION));
if ($storageExt !== '' && $baseExt === '') {
$raw .= '.'.$storageExt;
}
return $raw;
}
return $storageExt !== '' ? '附件.'.$storageExt : '附件';
}
/**
* PDF/图片在浏览器内联预览,其余类型用 attachment 以触发「保存为」时使用 clientDownloadName避免地址栏/标题仍显示 storage 随机名。
*/
public function preferredStreamDisposition(): string
{
$mime = strtolower((string) ($this->mime ?? ''));
if ($mime !== '') {
if (str_starts_with($mime, 'image/') || $mime === 'application/pdf') {
return 'inline';
}
return 'attachment';
}
$ext = strtolower((string) pathinfo($this->path, PATHINFO_EXTENSION));
if ($ext === 'pdf') {
return 'inline';
}
return 'attachment';
}
/**
* 选手端「预览」用 URL走 web 签名路由直出文件,不依赖 public/storage 符号链接(生产环境未 link 时 /storage/... 会 404
*/
public function participantPreviewSignedUrl(int $ttlSeconds = 172800): string
{
$u = URL::temporarySignedRoute(
'participant.application-file.download',
now()->addSeconds(max(60, $ttlSeconds)),
['file' => $this->id],
);
return preg_replace('#([^:])//+#', '$1/', $u) ?? $u;
}
1 month ago
}