1. 背景
ファイルアップロードプロジェクトを参照してください:クリックしてプレビューします
1. 最も簡単で一般的な方法はフォーム送信です。実際、フォーム送信なしでフロントエンドからバックエンドに送信することは困難です。ファイルと画像のアップロードを処理するには、一般に 2 つの方法があります
:
- まずアップロードし、リターン パスを取得してから、フォーム全体を送信してバックエンドに保存します。
- 通常のデータとファイル画像は同時にバックエンドに送信され、バックエンドによって処理されます。
利点の比較
- 1 つ目では、ファイルのアップロードに優先順位を付けて非同期に処理できるため、特に一部の大きなファイルの場合に、ユーザーが読み込みを送信する時間を節約できます。
- 2 番目の方法では、最後に送信された後にファイル処理のみが実行されるため、ダーティ データが発生せず、ファイル サーバーのスペースとトラフィックが節約されます。
デメリットを比べてみると、一つ目はファイルを選択してすぐにアップロードするだけですが、ユーザーは最終提出までにファイルを変更し続けることができるため、不要なファイル画像がアップロードされ続ける可能性があり、これらのダーティ ファイルを削除するために特定のロジックが使用されない限り (定期的なデータ フラッシュ、または送信時にユーザーの最終保存データを判断してダーティ データを削除する)
ここで著者は 2 番目の方法を採用していますが、これは最初の方法よりも実装が若干困難です。
2. フロントエンドHTMLの実装
要素は、成功時とエラー時に公式ドキュメントをアップロードします。実際、これらは上記の最初のメソッドでのみ使用されます。作成者は、要素は非同期方法で実装することが推奨されていると感じており、指定されたアップロード インターフェイスに送信されます。アクション。
フロントエンド実装のソースコード
<el-form-item label="图片" :required="form.postsType !== '2'">
<el-upload
action=""
list-type="picture-card"
:auto-upload="false"
:limit="9"
:before-upload="beforeUpload"
:on-change="handleChange"
:on-preview="handlePictureCardPreview"
:disabled="disabled"
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<div style="font-size: 12px;color: #666;">
只能上传jpg/png文件,且不超过 2MB,最多上传 9 张图片
</div>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</el-form-item>
属性も定義します
dialogImageUrl: '',//窗口预览图片路径
dialogVisible: false,//预览窗口是否打开
disabled: false,//是否禁用上传操作
ソースコード分析:
- :limit=“9” //写真は9枚までアップロード可能
- :before-upload=“beforeUpload”//アップロードする前に、画像を選択した後にメソッドが呼び出されます。
- :on-change=“ハンドル変更”//画像アップロード呼び出し方法を選択
- :on-preview=“handlePictureCardPreview”//プレビュー画像呼び出し方法
- :disabled=“無効”//アップロード操作を無効にするかどうか
- :on-remove=“ハンドル削除”//選択した画像をアップロードする
3.jsメソッドの実装
jsソースコード
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isLt2M
},
handleRemove(file, fileList) {
this.form.files = fileList;
console.info(this.form);
},
handleChange(file, fileList){
this.form.files = fileList;
console.info(this.form);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
ソースコード分析:
このメソッドの意味は上で説明したように、this.form.files はアップロードされたファイルを一時的に保存する配列として定義されています。
form: {
files: [],
title: ''
},
バックエンドにアップロードするデータ リクエストを組み立てます。
let formData = new FormData();
for (const file of this.form.files) {
//多个文件全部都放到files
if(file.raw) {
formData.append('files', file.raw);
}
}
formData.append('title',this.form.title);
add(formData).then(res => {
this.loading = false;
if(res.code === 200){
this.$message.success(res.msg);
}
},error => {
this.loading = false;
})
4.Javaバックエンド処理
コントローラ:
@PostMapping("/add")
@ApiOperation(value = "添加", notes = "添加")
@ApiImplicitParams({
@ApiImplicitParam(name = "title", value = "标题", required = true, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "files", value = "上传图片列表", required = false, dataType = "MultipartFile[]", paramType = "query")
})
public Result<Posts> add(
@RequestParam("title") String title,
@RequestParam(value = "files",required = false) MultipartFile[] files
) {
PostsReq postsReq = new PostsReq();
postsReq.setTitle(title);
postsReq.setFiles(files);
return postsService.add(JwtUtil.getUserId(),postsReq);
}
ソースコード分析:
作成者は当初 @RequestBody 注釈を使用してデータ オブジェクト全体を受信することを考えていましたが、これではエラーが発生します。作成者は具体的なエラー メッセージを記録していません。一般的な意味は、MultipartFile 型がサポートされておらず、コンストラクターが存在しないことです。次に、「MultipartFile のソース コードをチェックアウトする」を読みました。
これは実際にはインターフェイスです~、それで終わりです (もちろん、授業であるべきだと思います、ははは、不思議ではありません)。より詳細な研究を行った学生は、メッセージを残して共有してください。ありがとう!
Java ファイルアップロード処理の実装:
public String uploadImage(MultipartFile file) {
if (file == null)
throw new BizException("图片不能为空");
//得到上传文件的文件名
String fileName = file.getOriginalFilename();
//以传入的字符串开头,到该字符串的结尾,前开后闭
String suffixName = fileName.substring(fileName.lastIndexOf("."));
long size = file.getSize();
double mul = NumberUtil.div(size, (1024 * 1024), 2);
// 自定义异常
if (mul > 2)
throw new BizException("图片大小不能大于2M");
if (!isImage(suffixName))
throw new BizException("不是图片格式");
// 这里可以用uuid等 拼接新图片名
String newFileName = UUID.randomUUID().toString().replace("-", "") + suffixName;
// 创建路径
String destFileName = fileUploadConfig.getImageRealPath() + File.separator + newFileName;
File destFile = new File(destFileName);
if (!destFile.getParentFile().exists())
destFile.getParentFile().mkdirs();
try {
//将图片保存到文件夹里
file.transferTo(new File(destFileName));
} catch (IOException e) {
e.printStackTrace();
throw new BizException("图片上传错误");
}
//返回相对路径存储
return fileUploadConfig.getImageMapperPath() + newFileName;
}
/**
* 传进 .jpg 类似的格式 判断是否时图片格式
* @param suffixName 图片格式后缀
* @return
*/
public static boolean isImage(String suffixName) {
List<String> strings = Arrays.asList(".webp", ".png", ".jpg", ".jif", ".jpeg");
return strings.contains(suffixName);
}
それを達成するためのより良い方法がある場合は、メッセージを残して私たちと共有して、一緒に学び、進歩してください〜