今日はelementui経由でアップロードする際に発生した問題を記録しました。
ローカルにデプロイするサービス、フロントエンド サービスがバックエンド インターフェイスを要求する、クロスドメインの問題がある、
1. Springboot を使用して、ここには記載されていないクロスドメインの問題を解決できます。
2. リバース プロキシには vue 構成を使用します。
Vue はクロスドメインを解決します
vue.config.js ファイルで設定する
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
// 跨域请求
devServer: {
port: 8080,
// 开启代理
proxy: {
'/api': {
// 后端地址
target: 'http://localhost:8081/',
// 允许跨域
changeOrigin: true,
// 路径重写:我们可以应/api,替代上述后端url
pathRewrite: {
'^/api': '/'
}
}
}
}
})
写真をアップロードする
Javaコードは次のとおりです。
@RestController
@RequestMapping("/common")
@Api(tags = "文件controller")
public class CommonController {
@Value("${reggie.path}")
private String basePath;
@ApiOperation("文件上传")
@PostMapping("/upload")
public Result upLoad(@RequestParam("file") MultipartFile file) {
// 原始文件名 abc.jpc
String originalFilename = file.getOriginalFilename();
// 获取文件类型(jpg、png) .jpc
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
// 使用UUID重新生成文件名,防止文件名重复
String fileName = UUID.randomUUID() + suffix;
// 创建目录
File dir = new File(basePath);
if(!dir.exists()) {
dir.mkdirs();
}
try {
file.transferTo(new File(basePath + fileName)); // 当前目录下,生成图片,我们将这个路径返回
} catch (IOException e) {
e.printStackTrace();
}
return Result.success("文件上传成功", fileName);
}
@ApiOperation("文件下载")
@GetMapping("/download")
public void downLoad(String name, HttpServletResponse response) {
try {
// 输入流,通过输入流读取文件内容
FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));
// 输出流,通过输出流将文件写回浏览器
ServletOutputStream outputStream = response.getOutputStream();
response.setContentType("image/jpeg");
int len = 0;
byte[] bytes = new byte[1024]; // 缓存
while ((len = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
outputStream.flush();
}
//关闭资源
outputStream.close();
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
vueのコードは次のとおりです。
<el-upload action="/api/common/upload" //后端请求上传图片接口
list-type="picture-card"
:show-file-list="false" // 开启上传图片列表
:on-success="handleAvatarSuccess" // 成功响应后调用api,主要是这个
:before-upload="beforeAvatarUpload" //上传之前调用api
>
<i class="el-icon-plus"></i>
</el-upload>
<img :src="infoForm.avatar" alt="编辑头像" class="update-img">
バックエンドは上記のようにアップロード画像パスを指定します。クリックして画像をアップロードし、バックエンド インターフェイスをリクエストすると、画像は上記の場所にキャッシュされ、次の関数によって受信されます。
// 获得上传图片的url
handleAvatarSuccess(res, file) {
console.log(file, res);
this.infoForm.avatar = 'images/' + res.data
// 拿到二进制数据,是blob类型,存储到浏览器内存中,一刷新数据会消失
// console.log("imgUrl:", URL.createObjectURL(file.raw));
},
具体的に結果を受け入れます。
上記では、次の 2 つの方法で画像 URL を取得できます。
- BLOB と URL を取得しますが、 BLOB URL で表される画像はブラウザーのメモリ内にあり、ハードディスクには保存されていない ため、更新すると画像が消えます。
- 画像を使用/ + 画像名.jpg
具体的には: バックエンド キャッシュ パスは、vue プロジェクトの public/images フォルダーです。
なぜこのように使用するのでしょうか?
次のことについて話します。
1. Webpack でパッケージ化された Vue プロジェクトの構造が変更され、元のイメージ パスが無効になります。
2. public ファイルでは、静的リソースと同等であり、webpack によってパッケージ化されません。
3. Vue の静的パスと動的パス (変数) の分析は異なります。
詳細は以下のとおりです。